Skip to content

Commit

Permalink
widgets: add support for specifing size and position options via perc…
Browse files Browse the repository at this point in the history
…entages of output dimensions (#541)

* config: introduce a custom value type for layout related options

* widgets: use CLayoutValueData for size and position options

* widgets: catch bad_any_cast and out_of_range when contructing widgets other than label

* config: rename and restrict CLayoutValueData::fromAny to fromAnyPv

This is only for casting `any` variables that represent a void * to a
CLayoutValueData*, not just any any.

* misc: remove debug prints
  • Loading branch information
PaideiaDilemma authored Nov 6, 2024
1 parent 1cd3231 commit 4fc133c
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 92 deletions.
53 changes: 53 additions & 0 deletions src/config/ConfigDataValues.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once
#include "../helpers/Log.hpp"
#include <hyprutils/math/Vector2D.hpp>
#include <any>
#include <string>

enum eConfigValueDataTypes {
CVD_TYPE_INVALID = -1,
CVD_TYPE_LAYOUT = 0,
};

class ICustomConfigValueData {
public:
virtual ~ICustomConfigValueData() = 0;

virtual eConfigValueDataTypes getDataType() = 0;

virtual std::string toString() = 0;
};

class CLayoutValueData : public ICustomConfigValueData {
public:
CLayoutValueData() {};
virtual ~CLayoutValueData() {};

virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_LAYOUT;
}

virtual std::string toString() {
return std::format("{}{},{}{}", m_vValues.x, (m_sIsRelative.x) ? "%" : "px", m_vValues.y, (m_sIsRelative.y) ? "%" : "px");
}

static CLayoutValueData* fromAnyPv(const std::any& v) {
RASSERT(v.type() == typeid(void*), "Invalid config value type");
const auto P = (CLayoutValueData*)std::any_cast<void*>(v);
RASSERT(P, "Empty config value");
return P;
}

Hyprutils::Math::Vector2D getAbsolute(const Hyprutils::Math::Vector2D& viewport) {
return {
(m_sIsRelative.x ? (m_vValues.x / 100) * viewport.x : m_vValues.x),
(m_sIsRelative.y ? (m_vValues.y / 100) * viewport.y : m_vValues.y),
};
}

Hyprutils::Math::Vector2D m_vValues;
struct {
bool x = false;
bool y = false;
} m_sIsRelative;
};
63 changes: 56 additions & 7 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#include "ConfigManager.hpp"
#include "../helpers/MiscFunctions.hpp"
#include "../helpers/Log.hpp"
#include "../config/ConfigDataValues.hpp"
#include <hyprutils/path/Path.hpp>
#include <filesystem>
#include <glob.h>
#include <cstring>
#include <mutex>

ICustomConfigValueData::~ICustomConfigValueData() {
; // empty
}

static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
Expand All @@ -19,6 +24,51 @@ static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
return result;
}

static Hyprlang::CParseResult configHandleLayoutOption(const char* v, void** data) {
const std::string VALUE = v;

Hyprlang::CParseResult result;

if (!*data)
*data = new CLayoutValueData();

const auto DATA = (CLayoutValueData*)(*data);
const auto SPLIT = VALUE.find(',');
if (SPLIT == std::string::npos) {
result.setError(std::format("expected two comma seperated values, got {}", VALUE).c_str());
return result;
}

auto lhs = VALUE.substr(0, SPLIT);
auto rhs = VALUE.substr(SPLIT + 1);
if (rhs.starts_with(" "))
rhs = rhs.substr(1);

if (lhs.contains(",") || rhs.contains(",")) {
result.setError(std::format("too many arguments in {}", VALUE).c_str());
return result;
}

if (lhs.ends_with("%")) {
DATA->m_sIsRelative.x = true;
lhs.pop_back();
}

if (rhs.ends_with("%")) {
DATA->m_sIsRelative.y = true;
rhs.pop_back();
}

DATA->m_vValues = Hyprutils::Math::Vector2D{std::stof(lhs), std::stof(rhs)};

return result;
}

static void configHandleLayoutOptionDestroy(void** data) {
if (*data)
delete reinterpret_cast<CLayoutValueData*>(*data);
}

static std::string getMainConfigPath() {
static const auto paths = Hyprutils::Path::findConfig("hyprlock");
if (paths.first.has_value())
Expand All @@ -39,7 +89,6 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue(name, "shadow_passes", Hyprlang::INT{0}); \
m_config.addSpecialConfigValue(name, "shadow_color", Hyprlang::INT{0xFF000000}); \
m_config.addSpecialConfigValue(name, "shadow_boost", Hyprlang::FLOAT{1.2});

m_config.addConfigValue("general:disable_loading_bar", Hyprlang::INT{0});
m_config.addConfigValue("general:text_trim", Hyprlang::INT{1});
m_config.addConfigValue("general:hide_cursor", Hyprlang::INT{0});
Expand Down Expand Up @@ -69,12 +118,12 @@ void CConfigManager::init() {

m_config.addSpecialCategory("shape", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("shape", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("shape", "size", Hyprlang::VEC2{100, 100});
m_config.addSpecialConfigValue("shape", "size", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "100,100"});
m_config.addSpecialConfigValue("shape", "rounding", Hyprlang::INT{0});
m_config.addSpecialConfigValue("shape", "border_size", Hyprlang::INT{0});
m_config.addSpecialConfigValue("shape", "border_color", Hyprlang::INT{0xFF00CFE6});
m_config.addSpecialConfigValue("shape", "color", Hyprlang::INT{0xFF111111});
m_config.addSpecialConfigValue("shape", "position", Hyprlang::VEC2{0, 0});
m_config.addSpecialConfigValue("shape", "position", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "0,0"});
m_config.addSpecialConfigValue("shape", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("shape", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("shape", "rotate", Hyprlang::FLOAT{0});
Expand All @@ -89,7 +138,7 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("image", "rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("image", "border_size", Hyprlang::INT{4});
m_config.addSpecialConfigValue("image", "border_color", Hyprlang::INT{0xFFDDDDDD});
m_config.addSpecialConfigValue("image", "position", Hyprlang::VEC2{0, 0});
m_config.addSpecialConfigValue("image", "position", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "0,0"});
m_config.addSpecialConfigValue("image", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("image", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("image", "rotate", Hyprlang::FLOAT{0});
Expand All @@ -100,7 +149,7 @@ void CConfigManager::init() {

m_config.addSpecialCategory("input-field", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("input-field", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("input-field", "size", Hyprlang::VEC2{400, 90});
m_config.addSpecialConfigValue("input-field", "size", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "400,90"});
m_config.addSpecialConfigValue("input-field", "inner_color", Hyprlang::INT{0xFFDDDDDD});
m_config.addSpecialConfigValue("input-field", "outer_color", Hyprlang::INT{0xFF111111});
m_config.addSpecialConfigValue("input-field", "outline_thickness", Hyprlang::INT{4});
Expand All @@ -116,7 +165,7 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("input-field", "font_family", Hyprlang::STRING{"Sans"});
m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("input-field", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("input-field", "position", Hyprlang::VEC2{0, 0});
m_config.addSpecialConfigValue("input-field", "position", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "0,0"});
m_config.addSpecialConfigValue("input-field", "placeholder_text", Hyprlang::STRING{"<i>Input Password</i>"});
m_config.addSpecialConfigValue("input-field", "hide_input", Hyprlang::INT{0});
m_config.addSpecialConfigValue("input-field", "rounding", Hyprlang::INT{-1});
Expand All @@ -135,7 +184,7 @@ void CConfigManager::init() {

m_config.addSpecialCategory("label", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("label", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("label", "position", Hyprlang::VEC2{0, 0});
m_config.addSpecialConfigValue("label", "position", Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, "0,0"});
m_config.addSpecialConfigValue("label", "color", Hyprlang::INT{0xFFFFFFFF});
m_config.addSpecialConfigValue("label", "font_size", Hyprlang::INT{16});
m_config.addSpecialConfigValue("label", "text", Hyprlang::STRING{"Sample Text"});
Expand Down
5 changes: 0 additions & 5 deletions src/helpers/MiscFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,3 @@
#include <hyprutils/math/Vector2D.hpp>

std::string absolutePath(const std::string&, const std::string&);

//
inline Hyprutils::Math::Vector2D Vector2DFromHyprlang(const Hyprlang::VEC2& vec) {
return Hyprutils::Math::Vector2D{vec.x, vec.y};
};
32 changes: 19 additions & 13 deletions src/renderer/widgets/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "../Renderer.hpp"
#include "../../core/hyprlock.hpp"
#include "../../helpers/Log.hpp"
#include "../../helpers/MiscFunctions.hpp"
#include "../../config/ConfigDataValues.hpp"
#include <cmath>
#include <hyprlang.hpp>

Expand Down Expand Up @@ -82,18 +82,24 @@ void CImage::plantTimer() {
CImage::CImage(const Vector2D& viewport_, COutput* output_, const std::string& resourceID_, const std::unordered_map<std::string, std::any>& props) :
viewport(viewport_), resourceID(resourceID_), output(output_), shadow(this, props, viewport_) {

size = std::any_cast<Hyprlang::INT>(props.at("size"));
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
color = std::any_cast<Hyprlang::INT>(props.at("border_color"));
pos = Vector2DFromHyprlang(std::any_cast<Hyprlang::VEC2>(props.at("position")));
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));

path = std::any_cast<Hyprlang::STRING>(props.at("path"));
reloadTime = std::any_cast<Hyprlang::INT>(props.at("reload_time"));
reloadCommand = std::any_cast<Hyprlang::STRING>(props.at("reload_cmd"));
try {
size = std::any_cast<Hyprlang::INT>(props.at("size"));
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
color = std::any_cast<Hyprlang::INT>(props.at("border_color"));
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));

path = std::any_cast<Hyprlang::STRING>(props.at("path"));
reloadTime = std::any_cast<Hyprlang::INT>(props.at("reload_time"));
reloadCommand = std::any_cast<Hyprlang::STRING>(props.at("reload_cmd"));
} catch (const std::bad_any_cast& e) {
RASSERT(false, "Failed to construct CImage: {}", e.what()); //
} catch (const std::out_of_range& e) {
RASSERT(false, "Missing propperty for CImage: {}", e.what()); //
}

try {
modificationTime = std::filesystem::last_write_time(path);
Expand Down
37 changes: 17 additions & 20 deletions src/renderer/widgets/Label.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "../../helpers/Log.hpp"
#include "../../core/hyprlock.hpp"
#include "../../helpers/Color.hpp"
#include "../../helpers/MiscFunctions.hpp"
#include "../../config/ConfigDataValues.hpp"
#include <hyprlang.hpp>
#include <stdexcept>

Expand Down Expand Up @@ -73,7 +73,13 @@ void CLabel::plantTimer() {
CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string, std::any>& props, const std::string& output) :
outputStringPort(output), shadow(this, props, viewport_) {
try {
labelPreFormat = std::any_cast<Hyprlang::STRING>(props.at("text"));
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
labelPreFormat = std::any_cast<Hyprlang::STRING>(props.at("text"));
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
angle = angle * M_PI / 180.0;

std::string textAlign = std::any_cast<Hyprlang::STRING>(props.at("text_align"));
std::string fontFamily = std::any_cast<Hyprlang::STRING>(props.at("font_family"));
CColor labelColor = std::any_cast<Hyprlang::INT>(props.at("color"));
Expand All @@ -93,27 +99,18 @@ CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string,
if (!textAlign.empty())
request.props["text_align"] = textAlign;

g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);

pos = Vector2DFromHyprlang(std::any_cast<Hyprlang::VEC2>(props.at("position")));
configPos = pos;

viewport = viewport_;

halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));

angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
angle = angle * M_PI / 180.0;

plantTimer();
} catch (const std::bad_any_cast& e) {
Debug::log(ERR, "Failed to construct CLabel: {}", e.what());
throw;
RASSERT(false, "Failed to construct CLabel: {}", e.what()); //
} catch (const std::out_of_range& e) {
Debug::log(ERR, "Missing propperty for CLabel:{}", e.what());
throw;
RASSERT(false, "Missing property for CLabel: {}", e.what()); //
}

configPos = pos;
viewport = viewport_;

g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);

plantTimer();
}

bool CLabel::draw(const SRenderData& data) {
Expand Down
Loading

0 comments on commit 4fc133c

Please sign in to comment.