205 lines
6.4 KiB
C++
205 lines
6.4 KiB
C++
#pragma once
|
|
|
|
namespace att
|
|
{
|
|
enum class kAttribute : uint8_t {
|
|
Width, MinWidth, MaxWidth,
|
|
Height, MinHeight, MaxHeight,
|
|
Divisions, InnerRadius, OuterRadius,
|
|
Grow, Shrink, FlexDir, FlexWrap,
|
|
Padding, Margin,
|
|
Color
|
|
};
|
|
|
|
struct AttributeBase
|
|
{
|
|
kAttribute id;
|
|
};
|
|
|
|
typedef std::map<att::kAttribute, std::unique_ptr<att::AttributeBase>> AttrubutesMap;
|
|
|
|
template<kAttribute T, typename V>
|
|
struct Attribute : public AttributeBase
|
|
{
|
|
static const kAttribute static_id = T;
|
|
V value;
|
|
Attribute() : value{ 0 } { id = static_id; }
|
|
Attribute(V v) : value(v) { id = static_id; }
|
|
};
|
|
|
|
struct typemap
|
|
{
|
|
const char* name;
|
|
kAttribute value;
|
|
};
|
|
static constexpr typemap map[] =
|
|
{
|
|
{ "width", kAttribute::Width },
|
|
{ "min-width", kAttribute::MinWidth },
|
|
{ "max-width", kAttribute::MaxWidth },
|
|
{ "height", kAttribute::Height },
|
|
{ "min-height", kAttribute::MinHeight },
|
|
{ "max-height", kAttribute::MaxHeight },
|
|
{ "divisions", kAttribute::Divisions },
|
|
{ "inner-radius", kAttribute::InnerRadius },
|
|
{ "outer-radius", kAttribute::OuterRadius },
|
|
{ "grow", kAttribute::Grow },
|
|
{ "shrink", kAttribute::Shrink },
|
|
{ "dir", kAttribute::FlexDir },
|
|
{ "wrap", kAttribute::FlexWrap },
|
|
{ "pad", kAttribute::Padding },
|
|
{ "margin", kAttribute::Margin },
|
|
{ "color", kAttribute::Color },
|
|
};
|
|
static constexpr int map_size = sizeof(map) / sizeof(typemap) - 1;
|
|
constexpr bool same(const char* a, const char* b)
|
|
{
|
|
return (*a && *b) ? (*a == *b && same(a + 1, b + 1)) : !(*a || *b);
|
|
}
|
|
constexpr const kAttribute value(char const *name, int i = 0)
|
|
{
|
|
return ((i >= map_size) || same(map[i].name, name)) ?
|
|
map[i].value : value(name, i + 1);
|
|
}
|
|
constexpr const char* string(const kAttribute value, int i = 0)
|
|
{
|
|
return (map[i].value == value) ? map[i].name : string(value, i + 1);
|
|
}
|
|
|
|
//constexpr const char* string(kAttribute a) { return names[(int)a]; }
|
|
|
|
// template<kAttribute T, typename V>
|
|
// constexpr const char* string(const Attribute<T, V> a) { return names[(int)a.id]; }
|
|
|
|
#define DECLARE_ATTRIBUTE(N,T) \
|
|
struct N : public Attribute<kAttribute::N,T> \
|
|
{ using Attribute<kAttribute::N,T>::Attribute; };
|
|
|
|
DECLARE_ATTRIBUTE(Width, float);
|
|
DECLARE_ATTRIBUTE(MinWidth, float);
|
|
DECLARE_ATTRIBUTE(MaxWidth, float);
|
|
DECLARE_ATTRIBUTE(Height, float);
|
|
DECLARE_ATTRIBUTE(MinHeight, float);
|
|
DECLARE_ATTRIBUTE(MaxHeight, float);
|
|
DECLARE_ATTRIBUTE(Divisions, int);
|
|
DECLARE_ATTRIBUTE(InnerRadius, float);
|
|
DECLARE_ATTRIBUTE(OuterRadius, float);
|
|
DECLARE_ATTRIBUTE(Grow, float);
|
|
DECLARE_ATTRIBUTE(Shrink, float);
|
|
DECLARE_ATTRIBUTE(FlexDir, int);
|
|
DECLARE_ATTRIBUTE(FlexWrap, int);
|
|
DECLARE_ATTRIBUTE(Padding, glm::vec4);
|
|
DECLARE_ATTRIBUTE(Margin, glm::vec4);
|
|
DECLARE_ATTRIBUTE(Color, glm::vec4);
|
|
|
|
#undef DECLARE_ATTRIBUTE
|
|
}
|
|
|
|
class Node
|
|
{
|
|
const Node* parent{ nullptr };
|
|
YGNodeRef y_node{ nullptr };
|
|
struct stat m_file_info { 0 };
|
|
std::string m_path;
|
|
|
|
public:
|
|
std::vector<Node> children;
|
|
glm::vec4 color;
|
|
glm::vec2 m_pos;
|
|
glm::vec2 m_size;
|
|
glm::vec4 m_clip;
|
|
Node(const Node&) = delete;
|
|
Node& operator=(const Node&) = delete;
|
|
Node&& operator=(Node&& o) { return std::forward<Node>(o); }
|
|
Node(Node&& o)
|
|
{
|
|
children = std::move(o.children);
|
|
for (auto& c : children)
|
|
c.parent = this;
|
|
parent = o.parent;
|
|
y_node = o.y_node;
|
|
m_pos = o.m_pos;
|
|
m_size = o.m_size;
|
|
m_clip = o.m_clip;
|
|
color = o.color;
|
|
m_file_info = o.m_file_info;
|
|
o.y_node = nullptr;
|
|
o.parent = nullptr;
|
|
}
|
|
Node() { y_node = YGNodeNew(); }
|
|
~Node()
|
|
{
|
|
children.clear();
|
|
if (y_node)
|
|
YGNodeFree(y_node);
|
|
}
|
|
|
|
void SetWidth(float value) { YGNodeStyleSetWidth(y_node, value); }
|
|
void SetWidthP(float value) { YGNodeStyleSetWidthPercent(y_node, value); }
|
|
void SetHeight(float value) { YGNodeStyleSetHeight(y_node, value); }
|
|
void SetHeightP(float value) { YGNodeStyleSetHeightPercent(y_node, value); }
|
|
|
|
void SetPadding(float t, float r, float b, float l)
|
|
{
|
|
YGNodeStyleSetPadding(y_node, YGEdgeTop, t);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeRight, r);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeBottom, b);
|
|
YGNodeStyleSetPadding(y_node, YGEdgeLeft, l);
|
|
}
|
|
|
|
void SetFlexGrow(float value) { YGNodeStyleSetFlexGrow(y_node, value); }
|
|
void SetFlexShrink(float value) { YGNodeStyleSetFlexShrink(y_node, value); }
|
|
void SetFlexDir(YGFlexDirection value) { YGNodeStyleSetFlexDirection(y_node, value); }
|
|
void SetFlexWrap(YGWrap value) { YGNodeStyleSetFlexWrap(y_node, value); }
|
|
|
|
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b)
|
|
{
|
|
// convert from [x,y,w,h] to [x1,y1,x2,y1]
|
|
a = glm::vec4(a.xy(), a.xy() + a.zw());
|
|
b = glm::vec4(b.xy(), b.xy() + b.zw());
|
|
auto o = glm::vec4(glm::max(a.xy(), b.xy()), glm::min(a.zw(), b.zw()));
|
|
o = glm::vec4(o.xy(), glm::max({ 0, 0 }, o.zw() - o.xy()));
|
|
return o;
|
|
}
|
|
|
|
void update(float width, float height);
|
|
void update_internal(glm::vec2 origin);
|
|
void parse_attributes(att::kAttribute ka, const tinyxml2::XMLAttribute* attr);
|
|
void load(const char* path);
|
|
void load_internal(const tinyxml2::XMLElement* x_node);
|
|
void reload();
|
|
|
|
class iterator
|
|
{
|
|
std::stack<Node*> m_nodes;
|
|
Node* m_current;
|
|
public:
|
|
iterator(Node* root)
|
|
{
|
|
m_current = root;
|
|
if (root)
|
|
m_nodes.push(root);
|
|
}
|
|
iterator& operator++()
|
|
{
|
|
m_nodes.pop();
|
|
for (auto& c : m_current->children)
|
|
m_nodes.push(&c);
|
|
m_current = m_nodes.size() ? m_nodes.top() : nullptr;
|
|
return *this;
|
|
}
|
|
Node& operator*() { return *m_current; }
|
|
Node* operator->() { return m_current; }
|
|
bool operator==(const iterator& rhs) { return m_current == rhs.m_current; }
|
|
bool operator!=(const iterator& rhs) { return m_current != rhs.m_current; }
|
|
};
|
|
iterator begin()
|
|
{
|
|
return this;
|
|
}
|
|
iterator end()
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|