diff --git a/samples/demo/main.cpp b/samples/demo/main.cpp index 6ae09de..13f8f3b 100644 --- a/samples/demo/main.cpp +++ b/samples/demo/main.cpp @@ -57,8 +57,7 @@ int updateProgressbar(Id, void *instance) { } auto *widget = (Widget*) instance; - auto *eventPayload = (EventPayload*) widget->mContent; - if (eventPayload->type == EventDataType::FillState) { + if (auto *eventPayload = (EventPayload *)widget->mContent; eventPayload->type == EventDataType::FillState) { FilledState *state = (FilledState*) (eventPayload->payload); uint32_t tick = TinyUi::getTicks(); uint32_t diff = tick - LastTick; @@ -77,13 +76,12 @@ int updateProgressbar(Id, void *instance) { } int main(int argc, char *argv[]) { - Style style = TinyUi::getDefaultStyle(); - if (!TinyUi::createContext("Sample-Screen", style)) { + if (Style style = TinyUi::getDefaultStyle(); !TinyUi::createContext("Sample-Screen", style)) { return -1; } if (TinyUi::initScreen(20, 20, 1024, 768) == -1) { - auto &ctx = TinyUi::getContext(); + const auto &ctx = TinyUi::getContext(); ctx.mLogger(LogSeverity::Error, "Cannot init screen"); return ErrorCode; } diff --git a/samples/hello_world/main.cpp b/samples/hello_world/main.cpp index 82f2c9f..917c062 100644 --- a/samples/hello_world/main.cpp +++ b/samples/hello_world/main.cpp @@ -27,8 +27,6 @@ using namespace tinyui; static constexpr Id RootPanelId = 1; -static constexpr Id NextPanelId = 100; - int quit(Id, void *instance) { if (instance == nullptr) { return ErrorCode; @@ -41,13 +39,12 @@ int quit(Id, void *instance) { } int main(int argc, char *argv[]) { - Style style = TinyUi::getDefaultStyle(); - if (!TinyUi::createContext("Sample-Screen", style)) { + if (Style style = TinyUi::getDefaultStyle(); !TinyUi::createContext("Sample-Screen", style)) { return -1; } if (TinyUi::initScreen(20, 20, 1024, 768) == -1) { - auto &ctx = TinyUi::getContext(); + const auto &ctx = TinyUi::getContext(); ctx.mLogger(LogSeverity::Error, "Cannot init screen"); return ErrorCode; } @@ -55,7 +52,7 @@ int main(int argc, char *argv[]) { constexpr int32_t ButtonHeight = 20; Widgets::panel(RootPanelId, 0, "Sample-Dialog", Rect(90, 5, 220, 60), nullptr); auto &ctx = TinyUi::getContext(); - CallbackI *dynamicQuitCallback = new CallbackI(quit, (void*) &ctx); + auto *dynamicQuitCallback = new CallbackI(quit, (void*) &ctx); Widgets::label(2, RootPanelId, "Hi, World!", Rect(100, 10, 200, ButtonHeight), Alignment::Center); Widgets::button(3, RootPanelId, "Quit", Rect(100, 30, 200, ButtonHeight), dynamicQuitCallback); diff --git a/src/backends/sdl2_renderer.cpp b/src/backends/sdl2_renderer.cpp index 5315dbf..f00f119 100644 --- a/src/backends/sdl2_renderer.cpp +++ b/src/backends/sdl2_renderer.cpp @@ -186,8 +186,7 @@ ret_code Renderer::releaseRenderer(Context &ctx) { return ResultOk; } - SDLContext *sdlCtx = getBackendContext(ctx); - if (sdlCtx->mRenderer != nullptr) { + if (SDLContext *sdlCtx = getBackendContext(ctx); sdlCtx->mRenderer != nullptr) { SDL_DestroyRenderer(sdlCtx->mRenderer); sdlCtx->mRenderer = nullptr; } @@ -276,6 +275,7 @@ ret_code Renderer::initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int SDLContext *sdlCtx = SDLContext::create(); if (sdlCtx->mWindow != nullptr) { ctx.mLogger(LogSeverity::Error, "Already created."); + sdlCtx->destroy(); return ErrorCode; } @@ -448,7 +448,7 @@ ret_code Renderer::createRenderTexture(Context &ctx, int w, int h, SDL_Texture * return ResultOk; } -bool Renderer::update(Context &ctx) { +bool Renderer::update(const Context &ctx) { if (!ctx.mCreated) { return false; } @@ -513,7 +513,7 @@ SurfaceImpl *Renderer::createSurfaceImpl(unsigned char *data, int w, int h, int std::cerr << "*ERR*: %s\n" << errorMsg << "\n"; return nullptr; } - SurfaceImpl *surfaceImpl = new SurfaceImpl; + auto *surfaceImpl = new SurfaceImpl; surfaceImpl->mSurface = surface; return surfaceImpl; @@ -527,7 +527,7 @@ void Renderer::releaseSurfaceImpl(SurfaceImpl *surfaceImpl) { } ret_code Renderer::getSurfaceInfo(Context &ctx, int32_t &w, int32_t &h) { - SDLContext *sdlCtx = (SDLContext *) ctx.mBackendCtx->mHandle; + const auto *sdlCtx = (const SDLContext *) ctx.mBackendCtx->mHandle; if (sdlCtx->mSurface == nullptr) { return ErrorCode; } diff --git a/src/backends/sdl2_renderer.h b/src/backends/sdl2_renderer.h index 207a998..ff49cb5 100644 --- a/src/backends/sdl2_renderer.h +++ b/src/backends/sdl2_renderer.h @@ -119,7 +119,7 @@ struct Renderer { static ret_code endRender(Context &ctx); static ret_code createRenderTexture(Context &ctx, int w, int h, SDL_Texture **texture); static ret_code closeScreen(Context &ctx); - static bool update(Context &ctx); + static bool update(const Context &ctx); static SurfaceImpl *createSurfaceImpl(unsigned char *data, int w, int h, int bytesPerPixel, int pitch); static void releaseSurfaceImpl(SurfaceImpl *surfaceImpl); static ret_code getSurfaceInfo(Context &ctx, int32_t &w, int32_t &h); diff --git a/src/tinyui.cpp b/src/tinyui.cpp index 1507089..4796012 100644 --- a/src/tinyui.cpp +++ b/src/tinyui.cpp @@ -57,7 +57,7 @@ void log_message(LogSeverity severity, const char *message) { Context *gCtx = nullptr; Context *Context::create(const char *title, const Style &style) { - Context *ctx = new Context; + auto *ctx = new Context; ctx->mLogger = log_message; ctx->mAppTitle = title; ctx->mWindowsTitle = title; @@ -130,7 +130,7 @@ ret_code TinyUi::getSurfaceCenter(int32_t &x, int32_t &y) { } bool TinyUi::run() { - auto &ctx = getContext(); + const auto &ctx = getContext(); if (!ctx.mUpdateCallbackList.empty()) { for (auto it = ctx.mUpdateCallbackList.begin(); it != ctx.mUpdateCallbackList.end(); ++it) { (*it)->mfuncCallback[Events::UpdateEvent](1, (*it)->mInstance); @@ -150,7 +150,7 @@ ret_code TinyUi::endRender() { } void TinyUi::render() { - auto &ctx = getContext(); + const auto &ctx = getContext(); beginRender(ctx.mStyle.mClearColor); Widgets::renderWidgets(); endRender(); diff --git a/src/tinyui.h b/src/tinyui.h index 7aaf34b..299497c 100644 --- a/src/tinyui.h +++ b/src/tinyui.h @@ -60,6 +60,24 @@ SOFTWARE. # define _CRT_SECURE_NO_WARNINGS #endif +#if defined(_WIN32) || defined(_WIN64) +# define TINYUI_WINDOWS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN // Minimal windows header +# endif // WIN32_LEAN_AND_MEAN +#elif defined(__gnu_linux__) +# define TINYUI_GNU_LINUX +#elif defined(__APPLE__) || defined(__MACH__) +# error "Currently not supported platform" +#elif defined(__ANDROID__) +# define TINYUIE_ANDROID +#endif + +#ifdef TINYUI_WINDOWS +# include +# include +#endif + // Forward declarations ------------------------------------------------------- namespace tinyui { @@ -78,6 +96,10 @@ using Id = uint64_t; /// @brief The return code type used in the ui library. using ret_code = int32_t; +/// @brief The operation was cancelled. +static constexpr ret_code OpCancelled = -5; +/// @brief The context is invalid. +static constexpr ret_code InvalidContext = -4; /// @brief The invalid render handle return code. static constexpr ret_code InvalidRenderHandle = -3; /// @brief The invalid handle return code. @@ -220,14 +242,12 @@ struct Rect { top.y = r.top.y; } - const int x2_ = top.x + r.width; - if (bottom.x < x2_) { + if (const int x2_ = top.x + r.width; bottom.x < x2_) { bottom.x = x2_; width = r.width; } - const int y2_ = bottom.y + r.height; - if (bottom.y < y2_) { + if (const int y2_ = bottom.y + r.height; bottom.y < y2_) { bottom.y = y2_; height = r.height; } diff --git a/src/widgets.cpp b/src/widgets.cpp index 7f6e2b5..a88b83f 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -266,7 +266,7 @@ static int inputHandler(Id id, void *instance) { return ErrorCode; } - Context *ctx = static_cast(instance); + auto *ctx = static_cast(instance); ctx->mFocus = Widgets::findWidget(id, ctx->mRoot); return ResultOk; @@ -399,8 +399,7 @@ ret_code Widgets::panel(Id id, Id parentId, const char *title, const Rect &rect, return InvalidRenderHandle; } - Widget *child = createWidget(ctx, id, parentId, rect, WidgetType::Panel); - if (child == nullptr) { + if (const Widget *child = createWidget(ctx, id, parentId, rect, WidgetType::Panel); child == nullptr) { return ErrorCode; } @@ -412,6 +411,7 @@ static int onTreeViewItemClicked(Id id, void *data) { if (treeView == nullptr) { return ErrorCode; } + for (size_t i = 0; i < treeView->mChildren.size(); ++i ) { Widget *child = treeView->mChildren[i]; if (child == nullptr) { @@ -419,7 +419,9 @@ static int onTreeViewItemClicked(Id id, void *data) { } child->mEnabled = !child->mEnabled; } + std::cout << "TreeView item clicked: " << id << std::endl; + return 0; } @@ -432,7 +434,7 @@ ret_code Widgets::treeView(Id id, Id parentId, const char *title, const Rect &re if (ctx.mRoot == nullptr) { return InvalidRenderHandle; } - + Widget *widget = createWidget(ctx, id, parentId, rect, WidgetType::TreeView); if (widget == nullptr) { return ErrorCode; @@ -461,12 +463,12 @@ ret_code Widgets::treeItem(Id id, Id parentItemId, const char *text) { return InvalidRenderHandle; } - Widget *parentWidget = findWidget(parentItemId, ctx.mRoot); + const Widget *parentWidget = findWidget(parentItemId, ctx.mRoot); if (parentWidget == nullptr) { return ErrorCode; } - auto &parentRect = parentWidget->mRect; + const auto &parentRect = parentWidget->mRect; const int32_t margin = ctx.mStyle.mMargin; const int32_t w = parentRect.width; @@ -579,7 +581,7 @@ static void render(Context &ctx, const Widget *currentWidget) { if (payload == nullptr) { break; } - FilledState *state = reinterpret_cast(payload->payload); + const auto *state = reinterpret_cast(payload->payload); if (state == nullptr) { break; } @@ -771,7 +773,7 @@ void Widgets::setEnableState(Id id, bool enabled) { bool Widgets::isEnabled(Id id) { auto &ctx = TinyUi::getContext(); - Widget *widget = findWidget(id, ctx.mRoot); + const Widget *widget = findWidget(id, ctx.mRoot); if (widget != nullptr) { return widget->isEnabled(); } @@ -806,4 +808,90 @@ bool Widgets::endChild() { return true; } +static constexpr size_t BufferSize = 1024; + +ret_code Widgets::getOpenFileDialog(const char *title, const char *extensions, std::string &filename) { + filename.clear(); +#ifdef TINYUI_WINDOWS + // Init data + char szFile[BufferSize] = { '\0' }; + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szFile; + + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // use the contents of szFile to initialize itself. + ofn.lpstrTitle = title; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFilter = extensions; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = nullptr; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = nullptr; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + + // Display the Open dialog box. + if (::GetOpenFileName(&ofn) == TRUE) { + filename = ofn.lpstrFile; + } else { + return OpCancelled; + } +#else + char buffer[BufferSize] = { '\0' }; + FILE *f = popen("zenity --file-selection", "r"); + if (f == nullptr) { + return OpCancelled; + } + fgets(buffer, BufferSize, f); + filename = buffer; +#endif // TINYUI_WINDOWS + + return ResultOk; +} + +ret_code Widgets::getSaveFileDialog(const char *title, const char *extensions, std::string &filename) { + filename.clear(); + +#ifdef TINYUI_WINDOWS + char szFile[BufferSize] = { '\0' }; + // Initialize OPENFILENAME + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szFile; + + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // use the contents of szFile to initialize itself. + ofn.lpstrTitle = title; + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof(szFile); + ofn.lpstrFilter = extensions; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = nullptr; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = nullptr; + ofn.Flags = OFN_PATHMUSTEXIST; + + // Display the Open dialog box. + if (TRUE == GetSaveFileName(&ofn)) { + filename = ofn.lpstrFile; + } else { + return OpCancelled; + } +#else + FILE *f = popen("zenity --file-selection", "w"); + if (f == nullptr) { + return OpCancelled; + } + char buffer[BufferSize] = { '\0' }; + fgets(buffer, BufferSize, f); + + filename = buffer; +#endif // TINYUI_WINDOWS + + return ResultOk; +} + } // namespace tinyui diff --git a/src/widgets.h b/src/widgets.h index 4e06b82..e264654 100644 --- a/src/widgets.h +++ b/src/widgets.h @@ -337,6 +337,20 @@ struct Widgets { /// @brief Will close a child window. /// @return true if successful. static bool endChild(); + + /// @brief Will open a open-file-dialog. + /// @param title The title of the dialog. + /// @param extensions The allowed file extensions (e.g. "txt;pdf;docx"). + /// @param filename The selected filename. + /// @return true if a file was selected, false if the dialog was canceled. + static ret_code getOpenFileDialog(const char *title, const char *extensions, std::string &filename); + + /// @brief Will open a save-file-dialog. + /// @param title The title of the dialog. + /// @param extensions The allowed file extensions (e.g. "txt;pdf;docx"). + /// @param filename The selected filename. + /// @return true if a file was selected, false if the dialog was canceled. + static ret_code getSaveFileDialog(const char *title, const char *extensions, std::string &filename); }; } // namespace tinyui