From aebb3709066c8a480be8da1601319190dff420de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Mon, 17 Jul 2023 17:22:59 -0300 Subject: [PATCH] Add autoscrollbars feature to Lua API Dialog:show function --- src/app/script/dialog_class.cpp | 80 +++++++++++++++++++++++++++++++++ src/ui/fit_bounds.cpp | 3 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/app/script/dialog_class.cpp b/src/app/script/dialog_class.cpp index e1895b467..b0b590860 100644 --- a/src/app/script/dialog_class.cpp +++ b/src/app/script/dialog_class.cpp @@ -30,6 +30,7 @@ #include "ui/combobox.h" #include "ui/display.h" #include "ui/entry.h" +#include "ui/fit_bounds.h" #include "ui/grid.h" #include "ui/label.h" #include "ui/manager.h" @@ -39,6 +40,7 @@ #include "ui/separator.h" #include "ui/slider.h" #include "ui/system.h" +#include "ui/view.h" #include "ui/window.h" #include @@ -184,6 +186,65 @@ struct Dialog { } } + void addScrollbarsIfNeeded(const gfx::Rect& workarea, + gfx::Rect& bounds) + { + gfx::Rect rc = bounds; + + if (rc.x < workarea.x) { + rc.w -= (workarea.x - rc.x); + rc.x = workarea.x; + } + if (rc.x2() > workarea.x2()) { + rc.w = workarea.x2() - rc.x; + } + + bool vscrollbarsAdded = false; + if (rc.y < workarea.y) { + rc.h -= (workarea.y - rc.y); + rc.y = workarea.y; + vscrollbarsAdded = true; + } + if (rc.y2() > workarea.y2()) { + rc.h = workarea.y2() - rc.y; + vscrollbarsAdded = true; + } + + gfx::Rect newRc = rc; + if (get_multiple_displays() && window.shouldCreateNativeWindow()) { + const os::Window* nativeWindow = const_cast(parentDisplay())->nativeWindow(); + newRc.setOrigin(nativeWindow->pointFromScreen(rc.origin())); + newRc.setSize(rc.size() / nativeWindow->scale()); + } + if (newRc == window.bounds()) + return; + + View* view = new View(); + view->InitTheme.connect([view]{ view->noBorderNoChildSpacing(); }); + view->initTheme(); + + if (vscrollbarsAdded) { + int barWidth = view->verticalBar()->getBarWidth();; + if (get_multiple_displays()) + barWidth *= window.display()->scale(); + + rc.w += 2*barWidth; + if (rc.x2() > workarea.x2()) { + rc.x = workarea.x2() - rc.w; + if (rc.x < workarea.x) { + rc.x = workarea.x; + rc.w = workarea.w; + } + } + } + + // New bounds + bounds = rc; + + window.removeChild(&grid); + view->attachToView(&grid); + window.addChild(view); + } }; templaterefShow(L); bool wait = true; + bool autoScrollbars = false; obs::scoped_connection conn; if (lua_istable(L, 2)) { int type = lua_getfield(L, 2, "wait"); @@ -344,6 +406,24 @@ int Dialog_show(lua_State* L) } } lua_pop(L, 1); + + type = lua_getfield(L, 2, "autoscrollbars"); + if (type == LUA_TBOOLEAN) + autoScrollbars = lua_toboolean(L, -1); + lua_pop(L, 1); + } + + if (autoScrollbars) { + dlg->window.remapWindow(); + dlg->window.centerWindow(); + fit_bounds(dlg->parentDisplay(), + &dlg->window, + dlg->window.bounds(), + [dlg](const gfx::Rect& workarea, + gfx::Rect& bounds, + std::function getWidgetBounds) { + dlg->addScrollbarsIfNeeded(workarea, bounds); + }); } if (wait) diff --git a/src/ui/fit_bounds.cpp b/src/ui/fit_bounds.cpp index 810dee8eb..3f976e118 100644 --- a/src/ui/fit_bounds.cpp +++ b/src/ui/fit_bounds.cpp @@ -132,7 +132,8 @@ void fit_bounds(const Display* parentDisplay, frame.y = std::clamp(frame.y, workarea.y, std::max(workarea.y, workarea.y2() - frame.h)); // Set frame bounds directly - window->setBounds(gfx::Rect(0, 0, frame.w / scale, frame.h / scale)); + pos = nativeWindow->pointFromScreen(frame.origin()); + window->setBounds(gfx::Rect(pos.x, pos.y, frame.w / scale, frame.h / scale)); window->loadNativeFrame(frame); if (window->isVisible()) {