Skip to content

Commit

Permalink
Feature/shifted yoga style resolvers to shared file (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreamancuso authored Aug 5, 2024
1 parent ae06b17 commit 5a6e989
Show file tree
Hide file tree
Showing 4 changed files with 367 additions and 310 deletions.
67 changes: 47 additions & 20 deletions packages/dear-imgui/cpp/include/element/layout_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,36 @@ using json = nlohmann::json;
class ReactImgui;

class LayoutNode {
std::unordered_map<std::string, std::unique_ptr<IVariadicFn>, StringHash, std::equal_to<>> m_setters;

// Add a setter for any number of parameters
template <typename... Args>
void AddSetter(const std::string& key, std::function<void(Args...)> setter) {
m_setters[key] = std::make_unique<VariadicFnImpl<Args...>>(std::move(setter));
}

// Call a setter with variadic arguments
template <typename... Args>
void CallSetter(const std::string& key, Args... args) const {
auto it = m_setters.find(key);
if (it != m_setters.end()) {
void* arguments[] = { &args... };
it->second->call(arguments);
} else {
throw std::invalid_argument("Setter not found for key: " + key);
}
}

public:
YGNodeRef m_node;

LayoutNode();

size_t GetChildCount();
[[nodiscard]] size_t GetChildCount() const;

void InsertChild(LayoutNode* child, size_t index);
void InsertChild(LayoutNode* child, size_t index) const;

void ApplyStyle(const json& styleDef);
void ApplyStyle(const json& styleDef) const;

[[nodiscard]] YGNodeRef GetParentNode() const {
return YGNodeGetParent(m_node);
Expand Down Expand Up @@ -100,18 +120,10 @@ class LayoutNode {
YGNodeStyleSetPosition(m_node, edge, points);
}

void SetPositionPercent(const YGEdge edge, const float percent) const {
YGNodeStyleSetPositionPercent(m_node, edge, percent);
}

void SetMargin(const YGEdge edge, const float points) const {
YGNodeStyleSetMargin(m_node, edge, points);
}

void SetMarginPercent(const YGEdge edge, const float percent) const {
YGNodeStyleSetMarginPercent(m_node, edge, percent);
}

void SetMarginAuto(const YGEdge edge) const {
YGNodeStyleSetMarginAuto(m_node, edge);
}
Expand All @@ -120,10 +132,6 @@ class LayoutNode {
YGNodeStyleSetPadding(m_node, edge, points);
}

void SetPaddingPercent(const YGEdge edge, const float percent) const {
YGNodeStyleSetPaddingPercent(m_node, edge, percent);
}

void SetBorder(const YGEdge edge, const float border) const {
YGNodeStyleSetBorder(m_node, edge, border);
}
Expand Down Expand Up @@ -196,10 +204,29 @@ class LayoutNode {
YGNodeStyleSetMaxHeightPercent(m_node, percent);
}

std::optional<YGAlign> ResolveAlignItems(std::string def);

std::optional<YGEdge> ResolveEdge(const std::string& edgeKey);

std::optional<YGGutter> ResolveGutter(const std::string& gutterKey);
template <typename T, typename PropertyValueResolver>
void ApplyOptionalStyleProperty(const json& styleDef, const std::string& propertyKey, PropertyValueResolver resolver) const {
if (styleDef.contains(propertyKey) && styleDef[propertyKey].is_string()) {
auto rawValue = styleDef[propertyKey].template get<std::string>();
std::optional<T> value = resolver(rawValue);
if (value.has_value()) {
CallSetter<T>(propertyKey, value.value());
}
}
}

template <typename T1, typename T2, typename EdgeResolver>
void ApplyOptionalMultiEdgeStyleProperty(const json& styleDef, const std::string& propertyKey, EdgeResolver edgeResolver) const {
if (styleDef.contains(propertyKey) && styleDef[propertyKey].is_object()) {
for (auto& [key, item] : styleDef[propertyKey].items()) {
if (item.is_number()) {
std::optional<T1> edge = edgeResolver(key);
if (edge.has_value()) {
CallSetter<T1, T2>(propertyKey, edge.value(), item.template get<float>());
}
}
}
}
}
};

56 changes: 55 additions & 1 deletion packages/dear-imgui/cpp/include/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <variant>
#include <nlohmann/json.hpp>
#include <webgpu/webgpu.h>
#include <yoga/YGEnums.h>

#include "imgui.h"

#pragma once
Expand All @@ -11,6 +13,20 @@

using json = nlohmann::json;

// https://www.cppstories.com/2021/heterogeneous-access-cpp20/
struct StringHash {
using is_transparent = void;
[[nodiscard]] size_t operator()(const char *txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(std::string_view txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(const std::string &txt) const {
return std::hash<std::string>{}(txt);
}
};

enum HorizontalAlignment
{
// HorizontalAlignment_None = -1,
Expand Down Expand Up @@ -41,7 +57,7 @@ ImVec4 RGBAtoIV4(int r, int g, int b);
ImVec4 HEXAtoIV4(const char* hex, float a);
ImVec4 HEXAtoIV4(const char* hex);

float charPercentageToFloat(const char* input);
std::optional<float> charPercentageToFloat(const char* input);

json IV4toJson(ImVec4 imVec4);
json IV4toJsonTuple(ImVec4 imVec4);
Expand All @@ -58,6 +74,44 @@ struct Texture {
int height;
};

std::optional<YGAlign> ResolveAlignItems(std::string_view value);
std::optional<YGAlign> ResolveAlignContent(std::string_view value);
std::optional<YGJustify> ResolveJustifyContent(std::string_view value);
std::optional<YGFlexDirection> ResolveFlexDirection(std::string_view value);
std::optional<YGDirection> ResolveDirection(std::string_view value);
std::optional<YGPositionType> ResolvePositionType(std::string_view value);
std::optional<YGWrap> ResolveFlexWrap(std::string_view value);
std::optional<YGOverflow> ResolveOverflow(std::string_view value);
std::optional<YGDisplay> ResolveDisplay(std::string_view value);
std::optional<YGEdge> ResolveEdge(std::string_view edgeKey);
std::optional<YGGutter> ResolveGutter(std::string_view gutterKey);

// Base class for type-erased setters
struct IVariadicFn {
virtual ~IVariadicFn() = default;
virtual void call(void* args[]) = 0;
};

// Templated derived class for variadic setters
template <typename... Args>
class VariadicFnImpl : public IVariadicFn {
std::function<void(Args...)> setter;

public:
explicit VariadicFnImpl(std::function<void(Args...)> s) : setter(std::move(s)) {}

void call(void* args[]) override {
// Use std::apply to call the setter with unpacked arguments
callImpl(std::index_sequence_for<Args...>{}, args);
}

private:
template <std::size_t... I>
void callImpl(std::index_sequence<I...>, void* args[]) {
setter(*static_cast<Args*>(args[I])...);
}
};

bool LoadTexture(WGPUDevice device, const void* data, int numBytes, Texture* texture);

#endif
Loading

0 comments on commit 5a6e989

Please sign in to comment.