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
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,12 @@ results to

## Planned

- Datagrid
- Groups
- Tabs
- Togglebuttons
- Layouter
- Engine Integration
- Tutorials
1. Layouter
2. Copy & Paste
2. Groups
3. Tabs
4. Engine Integration examples
5. Tutorials

---

Expand Down
2 changes: 1 addition & 1 deletion contrib/vcpkg
Submodule vcpkg updated 1672 files
13 changes: 7 additions & 6 deletions src/backends/sdl2_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
return ResultOk;
}

ret_code Renderer::drawText(Context &ctx, const char *string, Font *font, const Rect &r, const Color4 &fgC,
ret_code Renderer::drawText(Context &ctx, const char *string, size_t maxLen, Font *font, const Rect &r, const Color4 &fgC,

Check warning on line 204 in src/backends/sdl2_renderer.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function has 8 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AaAUKRh9mx2U9V8z99ej&open=AaAUKRh9mx2U9V8z99ej&pullRequest=49
const Color4 &bgC, Alignment alignment) {
if (string == nullptr) {
return InvalidHandle;
Expand Down Expand Up @@ -238,26 +238,27 @@
ctx.mLogger(LogSeverity::Error, msg.c_str());
return ErrorCode;
}


const size_t stringLen = strnlen(string, maxLen);
int32_t margin{ctx.mStyle.mMargin};
SDL_Rect Message_rect{};
switch (alignment) {
case Alignment::Left:
Message_rect.x = r.top.x + margin;
Message_rect.y = r.top.y + margin;
Message_rect.w = font->mSize*static_cast<int>(strlen(string));
Message_rect.w = font->mSize*static_cast<int>(stringLen);
Message_rect.h = font->mSize + margin*2;
break;
case Alignment::Center:
Message_rect.x = r.top.x + 2 * margin + surfaceMessage->clip_rect.w / 2;
Message_rect.y = r.top.y + margin;
Message_rect.w = font->mSize * static_cast<int>(strlen(string));
Message_rect.w = font->mSize * static_cast<int>(stringLen);
Message_rect.h = font->mSize + margin * 2;
break;
case Alignment::Right:
Message_rect.x = r.top.x + surfaceMessage->clip_rect.w - static_cast<int>(font->mSize) * static_cast<int>(strlen(string));
Message_rect.x = r.top.x + surfaceMessage->clip_rect.w - static_cast<int>(font->mSize) * static_cast<int>(stringLen);
Message_rect.y = r.top.y + margin;
Message_rect.w = font->mSize * static_cast<int>(strlen(string));
Message_rect.w = font->mSize * static_cast<int>(stringLen);
Message_rect.h = font->mSize + margin * 2;
break;
case Alignment::Invalid:
Expand Down
2 changes: 1 addition & 1 deletion src/backends/sdl2_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct Renderer {
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);
static ret_code releaseScreen(Context &ctx);
static ret_code drawText(Context &ctx, const char *string, Font *font, const Rect &r, const Color4 &fgC, const Color4 &bgC, Alignment alignment);
static ret_code drawText(Context &ctx, const char *string, size_t maxLen, Font *font, const Rect &r, const Color4 &fgC, const Color4 &bgC, Alignment alignment);
static ret_code drawRect(Context &ctx, int32_t x, int32_t y, int32_t w, int32_t h, bool filled, Color4 fg);
static ret_code drawImage(Context &ctx, int32_t x, int32_t y, int32_t w, int32_t h, Image *image);
static ret_code beginRender(Context &ctx, Color4 bg, SDL_Texture *renderTarget = nullptr);
Expand Down
6 changes: 6 additions & 0 deletions src/tinyui.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,4 +569,10 @@ inline void clamp(T min, T max, T &value) {
}
}

#ifdef TINYUI_TRACE_ENABLED
# define TINYUI_TRACE(...) tinyui::TinyUi::getContext().mLogger(tinyui::LogSeverity::Trace, __VA_ARGS__)
#else
# define TINYUI_TRACE(...)
#endif TINYUI_TRACE_ENABLED

} // Namespace TinyUi
220 changes: 113 additions & 107 deletions src/widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,142 +38,148 @@ namespace tinyui {
static constexpr Id RootHandle = 1;

namespace {
Id createHandle() {
static Id id{ RootHandle };
return ++id;
}

Image *findImage(Context &ctx, const char *filename) {
if (filename == nullptr) {
return nullptr;
Id createHandle() {
static Id id{ RootHandle };
return ++id;
}

auto it = ctx.mImageCache.find(filename);
if (it == ctx.mImageCache.end()) {
return nullptr;
}
Image *findImage(Context &ctx, const char *filename) {
if (filename == nullptr) {
return nullptr;
}

return it->second;
}
auto it = ctx.mImageCache.find(filename);
if (it == ctx.mImageCache.end()) {
return nullptr;
}

Image *loadIntoImageCache(Context &ctx, const char *filename) {
if (filename == nullptr) {
return nullptr;
return it->second;
}

Image *image = findImage(ctx, filename);
if (image != nullptr) {
return image;
}
Image *loadIntoImageCache(Context &ctx, const char *filename) {
if (filename == nullptr) {
return nullptr;
}

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 *image = findImage(ctx, filename);
if (image != nullptr) {
return image;
}

image = new Image;
if (image == nullptr) {
return nullptr;
}
int w{ -1 };
int h{ -1 };
int bytesPerPixel{ -1 };
unsigned char *data = stbi_load(filename, &w, &h, &bytesPerPixel, 0);
if (data == 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;
image = new Image;
if (image == nullptr) {
return nullptr;
}

return 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;
ctx.mImageCache[filename] = 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;
}
return image;
}
ctx.mImageCache.clear();
}

Widget *getValidRoot(Context &ctx) {
if (ctx.mRoot != nullptr) {
return ctx.mRoot;
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();
}

ctx.mRoot = new Widget;
ctx.mRoot->mType = WidgetType::RootContainer;
ctx.mRoot->mHandle = WidgetHandle::getRootHandle();
Widget *getValidRoot(Context &ctx) {
if (ctx.mRoot != nullptr) {
return ctx.mRoot;
}

return ctx.mRoot;
}
ctx.mRoot = new Widget;
ctx.mRoot->mType = WidgetType::RootContainer;
ctx.mRoot->mHandle = WidgetHandle::getRootHandle();

Widget *setParent(Context &ctx, Widget *child, WidgetHandle parentId) {
Widget *parent{ nullptr };
if (parentId.mId == 0) {
parent = getValidRoot(ctx);
} else {
parent = Widgets::findWidget(parentId, ctx.mRoot);
return ctx.mRoot;
}

if (parent == nullptr) {
return nullptr;
}
Widget *setParent(Context &ctx, Widget *child, WidgetHandle parentId) {
Widget *parent{ nullptr };
if (parentId.mId == 0) {
parent = getValidRoot(ctx);
} else {
parent = Widgets::findWidget(parentId, ctx.mRoot);
}

parent->mChildren.emplace_back(child);
parent->mRect.mergeWithRect(child->mRect);
if (parent == nullptr) {
return nullptr;
}

return parent;
}
parent->mChildren.emplace_back(child);
parent->mRect.mergeWithRect(child->mRect);

Widget *createWidget(Context &ctx, WidgetHandle parentId, const Rect &rect, WidgetType type) {
auto *widget = new Widget;
widget->mHandle = WidgetHandle{ createHandle() };
widget->mType = type;
widget->mRect = rect;
widget->mParent = setParent(ctx, widget, parentId);
if (widget->mParent == nullptr) {
assert(widget->mParent != nullptr);
delete widget;
widget = nullptr;
return parent;
}

return widget;
}
Widget *createWidget(Context &ctx, WidgetHandle parentId, const Rect &rect, WidgetType type) {
auto *widget = new Widget;
widget->mHandle = WidgetHandle{ createHandle() };
widget->mType = type;
widget->mRect = rect;
widget->mParent = setParent(ctx, widget, parentId);
if (widget->mParent == nullptr) {
assert(widget->mParent != nullptr);
delete widget;
widget = nullptr;
}

void deleteKeyFromText(Context &ctx) {
ctx.mFocus->mText.erase(ctx.mFocus->mText.size() - 1);
}
return widget;
}

void appendKeyToText(Context &ctx, char *buffer) {
if (buffer == nullptr) {
return;
void deleteKeyFromText(Context &ctx) {
ctx.mFocus->mText.erase(ctx.mFocus->mText.size() - 1);
}

if (ctx.mFocus->mKeyInputType == KeyInputType::Numeric) {
if (buffer[0] < '0' || buffer[0] > '9') {
void appendKeyToText(Context &ctx, char *buffer) {
if (buffer == nullptr) {
TINYUI_TRACE("appendKeyToText: buffer is nullptr");
return;
}
if (ctx.mFocus == nullptr) {
TINYUI_TRACE("appendKeyToText: ctx.mFocus is nullptr");
return;
}

if (ctx.mFocus->mKeyInputType == KeyInputType::Numeric) {
if (buffer[0] < '0' || buffer[0] > '9') {
return;
}
}

ctx.mFocus->mText.append(buffer);
}

ctx.mFocus->mText.append(buffer);
}

void handleInputField(Context &ctx, EventPayload *eventPayload) {
char buffer[2] = {
static_cast<char>(eventPayload->payload[0]),
'\0'
};
if (buffer[0] == SDLK_BACKSPACE) {
deleteKeyFromText(ctx);
} else {
appendKeyToText(ctx, buffer);
void handleInputField(Context &ctx, EventPayload *eventPayload) {
char buffer[2] = {
static_cast<char>(eventPayload->payload[0]),
'\0'
};
if (buffer[0] == SDLK_BACKSPACE) {
deleteKeyFromText(ctx);
} else {
appendKeyToText(ctx, buffer);
}
}
}
} // namespace

void eventDispatcher(Context &ctx, int32_t eventId, EventPayload *eventPayload) {
Expand Down Expand Up @@ -545,7 +551,7 @@ static void render(Context &ctx, const Widget *currentWidget) {
if (!currentWidget->mText.empty()) {
const Color4 fg = ctx.mStyle.mTextColor;
const Color4 bg = ctx.mStyle.mBg;
Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont,
Renderer::drawText(ctx, currentWidget->mText.c_str(), currentWidget->mText.length(), ctx.mDefaultFont,
currentWidget->mRect, fg, bg, currentWidget->mAlignment);
}
}
Expand All @@ -557,7 +563,7 @@ static void render(Context &ctx, const Widget *currentWidget) {
if (!currentWidget->mText.empty()) {
const Color4 fg = ctx.mStyle.mTextColor;
const Color4 bg = ctx.mStyle.mBg;
Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont,
Renderer::drawText(ctx, currentWidget->mText.c_str(), currentWidget->mText.length(), ctx.mDefaultFont,
currentWidget->mRect, fg, bg, currentWidget->mAlignment);
}
}
Expand All @@ -568,7 +574,7 @@ static void render(Context &ctx, const Widget *currentWidget) {
if (!currentWidget->mText.empty()) {
const Color4 fg = ctx.mStyle.mTextColor;
const Color4 bg = ctx.mStyle.mBg;
Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont,
Renderer::drawText(ctx, currentWidget->mText.c_str(), currentWidget->mText.length(), ctx.mDefaultFont,
currentWidget->mRect, fg, bg, currentWidget->mAlignment);
}
}
Expand Down Expand Up @@ -614,7 +620,7 @@ static void render(Context &ctx, const Widget *currentWidget) {
const Color4 fg = ctx.mStyle.mTextColor;
const Color4 bg = ctx.mStyle.mBg;
Rect textRect(checkBoxRect.top.x + checkBoxRect.width + 5, r.top.y, r.width - checkBoxRect.width - 5, r.height);
Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont,
Renderer::drawText(ctx, currentWidget->mText.c_str(), currentWidget->mText.length(), ctx.mDefaultFont,
textRect, fg, bg, currentWidget->mAlignment);
}
}
Expand All @@ -628,7 +634,7 @@ static void render(Context &ctx, const Widget *currentWidget) {
if (!currentWidget->mText.empty()) {
const Color4 fg = ctx.mStyle.mTextColor;
const Color4 bg = ctx.mStyle.mBg;
Renderer::drawText(ctx, currentWidget->mText.c_str(), ctx.mDefaultFont,
Renderer::drawText(ctx, currentWidget->mText.c_str(), currentWidget->mText.length(), ctx.mDefaultFont,
currentWidget->mRect, fg, bg, currentWidget->mAlignment);
}
}
Expand Down
Loading