Esp32-RBGridUI
Library for creating UIs for the RBController app
Loading...
Searching...
No Matches
widget.cpp
Go to the documentation of this file.
1#include <memory>
2
3#include "../gridui.h"
4#include "rbprotocol.h"
5#include "widget.h"
6
7namespace gridui {
8
9std::mutex WidgetState::m_mutex;
10
11WidgetState Widget::emptyState(0, 0, 0, 0, 0, 0);
12
13WidgetState::WidgetState(uint16_t uuid, float x, float y, float w, float h, uint16_t tab)
14 : m_uuid(uuid)
15 , m_bloom_global(0)
16 , m_bloom_tick(0) {
17
18 char buf[9];
19 snprintf(buf, sizeof(buf), "%lx", WidgetPos(x, y, w, h).encoded());
20 m_data.set("p", new rbjson::String(buf));
21
22 if(tab != 0) {
23 m_data.set("tab", tab);
24 }
25}
26
27std::string WidgetState::getString(const std::string& key, std::string def) const {
28 std::unique_lock<std::mutex> lock(m_mutex);
29 return m_data.getString(key, def);
30}
31
32int64_t WidgetState::getInt(const std::string& key, int64_t def) const {
33 std::unique_lock<std::mutex> lock(m_mutex);
34 return m_data.getInt(key, def);
35}
36
37double WidgetState::getDouble(const std::string& key, double def) const {
38 std::unique_lock<std::mutex> lock(m_mutex);
39 return m_data.getDouble(key, def);
40}
41
42bool WidgetState::getBool(const std::string& key, bool def) const {
43 std::unique_lock<std::mutex> lock(m_mutex);
44 return m_data.getBool(key, def);
45}
46
47bool WidgetState::set(const std::string& key, rbjson::Value* value) {
48 if (m_uuid == 0)
49 return false;
50
51 std::unique_lock<std::mutex> lock(m_mutex);
52
53 const auto* old = m_data.get(key);
54 if (old != nullptr && old->equals(*value)) {
55 delete value;
56 return false;
57 }
58
59 m_data.set(key, value);
60 markChangedLocked(key);
61 return true;
62}
63
64bool WidgetState::setInnerObjectProp(const std::string& objectName, const std::string& propertyName, rbjson::Value* value) {
65 if (m_uuid == 0)
66 return false;
67
68 std::unique_lock<std::mutex> lock(m_mutex);
69
70 auto* obj = m_data.getObject(objectName);
71 if (obj == nullptr) {
72 obj = new rbjson::Object;
73 m_data.set(objectName, obj);
74 } else {
75 const auto* old = obj->get(propertyName);
76 if (old != nullptr && old->equals(*value)) {
77 delete value;
78 return false;
79 }
80 }
81
82 obj->set(propertyName, value);
83 markChangedLocked(objectName);
84 return true;
85}
86
87bool WidgetState::popChanges(rbjson::Object& state) {
88 std::unique_lock<std::mutex> lock(m_mutex);
89 if (m_bloom_tick == 0)
90 return false;
91
92 const auto& m = m_data.members();
93 for (auto itr = m.begin(); itr != m.end(); ++itr) {
94 if (wasChangedInTickLocked(itr->name, itr->name_len)) {
95 state.set(std::string(itr->name, itr->name_len), itr->value->copy());
96 }
97 }
98 m_bloom_tick = 0;
99 return true;
100}
101
102static inline uint32_t murmur3_32(const uint8_t* key, size_t len, uint32_t seed) {
103 uint32_t h = seed;
104 if (len > 3) {
105 const uint32_t* key_x4 = (const uint32_t*)key;
106 size_t i = len >> 2;
107 do {
108 uint32_t k = *key_x4++;
109 k *= 0xcc9e2d51;
110 k = (k << 15) | (k >> 17);
111 k *= 0x1b873593;
112 h ^= k;
113 h = (h << 13) | (h >> 19);
114 h = (h * 5) + 0xe6546b64;
115 } while (--i);
116 key = (const uint8_t*)key_x4;
117 }
118 if (len & 3) {
119 size_t i = len & 3;
120 uint32_t k = 0;
121 key = &key[i - 1];
122 do {
123 k <<= 8;
124 k |= *key--;
125 } while (--i);
126 k *= 0xcc9e2d51;
127 k = (k << 15) | (k >> 17);
128 k *= 0x1b873593;
129 h ^= k;
130 }
131 h ^= len;
132 h ^= h >> 16;
133 h *= 0x85ebca6b;
134 h ^= h >> 13;
135 h *= 0xc2b2ae35;
136 h ^= h >> 16;
137 return h;
138}
139
140static constexpr int hash_count = 3;
141
142void WidgetState::markChanged(const std::string& key) {
143 if (m_uuid == 0)
144 return;
145
146 std::unique_lock<std::mutex> lock(m_mutex);
147 markChangedLocked(key);
148}
149
150void WidgetState::markChangedLocked(const std::string& key) {
151 for (int i = 0; i < hash_count; ++i) {
152 const auto bit = murmur3_32((uint8_t*)key.c_str(), key.size(), i) % 16;
153 m_bloom_global |= (1 << bit);
154 m_bloom_tick |= (1 << bit);
155 }
156
157 UI.notifyStateChange();
158}
159
160void WidgetState::markGlobalChangedLocked(const std::string& key) {
161 for (int i = 0; i < hash_count; ++i) {
162 const auto bit = murmur3_32((uint8_t*)key.c_str(), key.size(), i) % 16;
163 m_bloom_global |= (1 << bit);
164 }
165}
166
167bool WidgetState::wasChangedInTickLocked(const char *key, size_t key_len) const {
168 for (int i = 0; i < hash_count; ++i) {
169 const auto bit = murmur3_32((uint8_t*)key, key_len, i) % 16;
170 if ((m_bloom_tick & (1 << bit)) == 0)
171 return false;
172 }
173 return true;
174}
175
176bool WidgetState::remarkAllChanges() {
177 std::unique_lock<std::mutex> lock(m_mutex);
178 if (m_bloom_global == 0)
179 return false;
180 m_bloom_tick = m_bloom_global;
181 return true;
182}
183};
bool set(const std::string &key, rbjson::Value *value)
Definition widget.cpp:47
bool setInnerObjectProp(const std::string &objectName, const std::string &propertyName, rbjson::Value *value)
Definition widget.cpp:64
void markChanged(const std::string &key)
Definition widget.cpp:142
std::string getString(const std::string &key, std::string def="") const
Definition widget.cpp:27
WidgetState(uint16_t uuid, float x, float y, float w, float h, uint16_t tab)
Definition widget.cpp:13
int64_t getInt(const std::string &key, int64_t def=0) const
Definition widget.cpp:32
bool getBool(const std::string &key, bool def=false) const
Definition widget.cpp:42
double getDouble(const std::string &key, double def=0.0) const
Definition widget.cpp:37
Definition arm.h:8
_GridUi UI
Definition gridui.cpp:14
static uint32_t murmur3_32(const uint8_t *key, size_t len, uint32_t seed)
Definition widget.cpp:102
static constexpr int hash_count
Definition widget.cpp:140