From d1f542a75f8ee9fcf40c534729ea6e503280382c Mon Sep 17 00:00:00 2001 From: bvr-yr <130279855+bvr-yr@users.noreply.github.com> Date: Mon, 4 Mar 2024 20:59:36 +0300 Subject: [PATCH] input-field: add dots rounding option (#130) * refactor: move dot props to struct, rename to camelCase * input-field: add dots rounding option * render: minor fix for odd input-field width * add dots_rounding option to Home Manager --- nix/hm-module.nix | 6 ++++ src/config/ConfigManager.cpp | 2 ++ src/renderer/widgets/PasswordInputField.cpp | 33 +++++++++++++-------- src/renderer/widgets/PasswordInputField.hpp | 10 +++---- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 02fd10e..7e6c7f1 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -181,6 +181,12 @@ in { default = true; }; + dots_rounding = mkOption { + description = "The rounding of dots (-2 follows input-field rounding)"; + type = int; + default = -1; + }; + outer_color = mkOption { description = "The outer color of the input field"; type = str; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7761a7d..59c473c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -61,6 +61,7 @@ void CConfigManager::init() { m_config.addSpecialConfigValue("input-field", "dots_size", Hyprlang::FLOAT{0.25}); m_config.addSpecialConfigValue("input-field", "dots_center", Hyprlang::INT{1}); m_config.addSpecialConfigValue("input-field", "dots_spacing", Hyprlang::FLOAT{0.2}); + m_config.addSpecialConfigValue("input-field", "dots_rounding", Hyprlang::INT{-1}); m_config.addSpecialConfigValue("input-field", "fade_on_empty", Hyprlang::INT{1}); m_config.addSpecialConfigValue("input-field", "font_color", Hyprlang::INT{0xFF000000}); m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"}); @@ -136,6 +137,7 @@ std::vector CConfigManager::getWidgetConfigs() { {"dots_size", m_config.getSpecialConfigValue("input-field", "dots_size", k.c_str())}, {"dots_spacing", m_config.getSpecialConfigValue("input-field", "dots_spacing", k.c_str())}, {"dots_center", m_config.getSpecialConfigValue("input-field", "dots_center", k.c_str())}, + {"dots_rounding", m_config.getSpecialConfigValue("input-field", "dots_rounding", k.c_str())}, {"fade_on_empty", m_config.getSpecialConfigValue("input-field", "fade_on_empty", k.c_str())}, {"font_color", m_config.getSpecialConfigValue("input-field", "font_color", k.c_str())}, {"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())}, diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index 208b84c..41d08c4 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -7,10 +7,11 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u size = std::any_cast(props.at("size")); inner = std::any_cast(props.at("inner_color")); outer = std::any_cast(props.at("outer_color")); - out_thick = std::any_cast(props.at("outline_thickness")); - dt_size = std::any_cast(props.at("dots_size")); - dt_space = std::any_cast(props.at("dots_spacing")); + outThick = std::any_cast(props.at("outline_thickness")); + dots.size = std::any_cast(props.at("dots_size")); + dots.spacing = std::any_cast(props.at("dots_spacing")); dots.center = std::any_cast(props.at("dots_center")); + dots.rounding = std::any_cast(props.at("dots_rounding")); fadeOnEmpty = std::any_cast(props.at("fade_on_empty")); font = std::any_cast(props.at("font_color")); pos = std::any_cast(props.at("position")); @@ -18,9 +19,9 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u rounding = std::any_cast(props.at("rounding")); viewport = viewport_; - pos = posFromHVAlign(viewport, size, pos, std::any_cast(props.at("halign")), std::any_cast(props.at("valign"))); - dt_size = std::clamp(dt_size, 0.2f, 0.8f); - dt_space = std::clamp(dt_space, 0.f, 1.f); + pos = posFromHVAlign(viewport, size, pos, std::any_cast(props.at("halign")), std::any_cast(props.at("valign"))); + dots.size = std::clamp(dots.size, 0.2f, 0.8f); + dots.spacing = std::clamp(dots.spacing, 0.f, 1.f); std::string placeholderText = std::any_cast(props.at("placeholder_text")); if (!placeholderText.empty()) { @@ -102,7 +103,7 @@ void CPasswordInputField::updateDots() { bool CPasswordInputField::draw(const SRenderData& data) { CBox inputFieldBox = {pos, size}; - CBox outerBox = {pos - Vector2D{out_thick, out_thick}, size + Vector2D{out_thick * 2, out_thick * 2}}; + CBox outerBox = {pos - Vector2D{outThick, outThick}, size + Vector2D{outThick * 2, outThick * 2}}; bool forceReload = false; @@ -139,10 +140,10 @@ bool CPasswordInputField::draw(const SRenderData& data) { glDisable(GL_SCISSOR_TEST); } - g_pRenderer->renderRect(inputFieldBox, innerCol, rounding == -1 ? inputFieldBox.h / 2.0 : rounding - out_thick); + g_pRenderer->renderRect(inputFieldBox, innerCol, rounding == -1 ? inputFieldBox.h / 2.0 : rounding - outThick); - const int PASS_SIZE = std::nearbyint(inputFieldBox.h * dt_size * 0.5f) * 2.f; - const int PASS_SPACING = std::floor(PASS_SIZE * dt_space); + const int PASS_SIZE = std::nearbyint(inputFieldBox.h * dots.size * 0.5f) * 2.f; + const int PASS_SPACING = std::floor(PASS_SIZE * dots.spacing); const int DOT_PAD = (inputFieldBox.h - PASS_SIZE) / 2; const int DOT_AREA_WIDTH = inputFieldBox.w - DOT_PAD * 2; // avail width for dots const int MAX_DOTS = std::round(DOT_AREA_WIDTH * 1.0 / (PASS_SIZE + PASS_SPACING)); // max amount of dots that can fit in the area @@ -158,6 +159,11 @@ bool CPasswordInputField::draw(const SRenderData& data) { if (dots.currentAmount > MAX_DOTS) xstart = (inputFieldBox.w + MAX_DOTS * (PASS_SIZE + PASS_SPACING) - PASS_SPACING - 2 * TOTAL_DOTS_WIDTH) / 2; + if (dots.rounding == -1) + dots.rounding = PASS_SIZE / 2.0; + else if (dots.rounding == -2) + dots.rounding = rounding == -1 ? PASS_SIZE / 2.0 : rounding * dots.size; + for (int i = 0; i < dots.currentAmount; ++i) { if (i < DOT_FLOORED - MAX_DOTS) continue; @@ -169,9 +175,10 @@ bool CPasswordInputField::draw(const SRenderData& data) { fontCol.a *= (1 - dots.currentAmount + DOT_FLOORED) * data.opacity; } - Vector2D dotPosition = inputFieldBox.pos() + Vector2D{xstart + i * (PASS_SIZE + PASS_SPACING), inputFieldBox.h / 2.f - PASS_SIZE / 2.f}; - CBox box{dotPosition, Vector2D{PASS_SIZE, PASS_SIZE}}; - g_pRenderer->renderRect(box, fontCol, PASS_SIZE / 2.0); + Vector2D dotPosition = + inputFieldBox.pos() + Vector2D{xstart + (int)inputFieldBox.w % 2 / 2.f + i * (PASS_SIZE + PASS_SPACING), inputFieldBox.h / 2.f - PASS_SIZE / 2.f}; + CBox box{dotPosition, Vector2D{PASS_SIZE, PASS_SIZE}}; + g_pRenderer->renderRect(box, fontCol, dots.rounding); fontCol.a = DOT_ALPHA; } } diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index 6ec548b..49c51d3 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -26,9 +26,7 @@ class CPasswordInputField : public IWidget { Vector2D pos; Vector2D viewport; - float dt_size, dt_space; - - int out_thick; + int outThick, rounding; CColor inner, outer, font; @@ -36,7 +34,10 @@ class CPasswordInputField : public IWidget { float currentAmount = 0; float speedPerSecond = 5; // actually per... something. I am unsure xD std::chrono::system_clock::time_point lastFrame; - bool center = false; + bool center = false; + float size = 0; + float spacing = 0; + int rounding = 0; } dots; struct { @@ -63,5 +64,4 @@ class CPasswordInputField : public IWidget { } hiddenInputState; bool fadeOnEmpty; - int rounding; };