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
27bool WidgetState::set(const std::string& key, rbjson::Value* value) {
28 if (m_uuid == 0)
29 return false;
30
31 std::lock_guard<std::mutex> lock(m_mutex);
32
33 const auto* old = m_data.get(key);
34 if (old != nullptr && old->equals(*value)) {
35 delete value;
36 return false;
37 }
38
39 m_data.set(key, value);
40 markChangedLocked(key);
41 return true;
42}
43
44bool WidgetState::setInnerObjectProp(const std::string& objectName, const std::string& propertyName, rbjson::Value* value) {
45 if (m_uuid == 0)
46 return false;
47
48 std::lock_guard<std::mutex> lock(m_mutex);
49
50 auto* obj = m_data.getObject(objectName);
51 if (obj == nullptr) {
52 obj = new rbjson::Object;
53 m_data.set(objectName, obj);
54 } else {
55 const auto* old = obj->get(propertyName);
56 if (old != nullptr && old->equals(*value)) {
57 delete value;
58 return false;
59 }
60 }
61
62 obj->set(propertyName, value);
63 markChangedLocked(objectName);
64 return true;
65}
66
67bool WidgetState::popChanges(rbjson::Object& state) {
68 std::lock_guard<std::mutex> lock(m_mutex);
69 if (m_bloom_tick == 0)
70 return false;
71
72 const auto& m = m_data.members();
73 for (auto itr = m.begin(); itr != m.end(); ++itr) {
74 if (wasChangedInTickLocked(itr->name, itr->name_len)) {
75 state.set(std::string(itr->name, itr->name_len), itr->value->copy());
76 }
77 }
78 m_bloom_tick = 0;
79 return true;
80}
81
82static inline uint32_t murmur3_32(const uint8_t* key, size_t len, uint32_t seed) {
83 uint32_t h = seed;
84 if (len > 3) {
85 const uint32_t* key_x4 = (const uint32_t*)key;
86 size_t i = len >> 2;
87 do {
88 uint32_t k = *key_x4++;
89 k *= 0xcc9e2d51;
90 k = (k << 15) | (k >> 17);
91 k *= 0x1b873593;
92 h ^= k;
93 h = (h << 13) | (h >> 19);
94 h = (h * 5) + 0xe6546b64;
95 } while (--i);
96 key = (const uint8_t*)key_x4;
97 }
98 if (len & 3) {
99 size_t i = len & 3;
100 uint32_t k = 0;
101 key = &key[i - 1];
102 do {
103 k <<= 8;
104 k |= *key--;
105 } while (--i);
106 k *= 0xcc9e2d51;
107 k = (k << 15) | (k >> 17);
108 k *= 0x1b873593;
109 h ^= k;
110 }
111 h ^= len;
112 h ^= h >> 16;
113 h *= 0x85ebca6b;
114 h ^= h >> 13;
115 h *= 0xc2b2ae35;
116 h ^= h >> 16;
117 return h;
118}
119
120static constexpr int hash_count = 3;
121
122void WidgetState::markChanged(const std::string& key) {
123 if (m_uuid == 0)
124 return;
125
126 std::lock_guard<std::mutex> lock(m_mutex);
127 markChangedLocked(key);
128}
129
130void WidgetState::markChangedLocked(const std::string& key) {
131 for (int i = 0; i < hash_count; ++i) {
132 const auto bit = murmur3_32((uint8_t*)key.c_str(), key.size(), i) % 16;
133 m_bloom_global |= (1 << bit);
134 m_bloom_tick |= (1 << bit);
135 }
136
137 UI.notifyStateChange();
138}
139
140void WidgetState::markGlobalChangedLocked(const std::string& key) {
141 for (int i = 0; i < hash_count; ++i) {
142 const auto bit = murmur3_32((uint8_t*)key.c_str(), key.size(), i) % 16;
143 m_bloom_global |= (1 << bit);
144 }
145}
146
147bool WidgetState::wasChangedInTickLocked(const char *key, size_t key_len) const {
148 for (int i = 0; i < hash_count; ++i) {
149 const auto bit = murmur3_32((uint8_t*)key, key_len, i) % 16;
150 if ((m_bloom_tick & (1 << bit)) == 0)
151 return false;
152 }
153 return true;
154}
155
156bool WidgetState::remarkAllChanges() {
157 std::lock_guard<std::mutex> lock(m_mutex);
158 if (m_bloom_global == 0)
159 return false;
160 m_bloom_tick = m_bloom_global;
161 return true;
162}
163};
bool set(const std::string &key, rbjson::Value *value)
Definition widget.cpp:27
bool setInnerObjectProp(const std::string &objectName, const std::string &propertyName, rbjson::Value *value)
Definition widget.cpp:44
void markChanged(const std::string &key)
Definition widget.cpp:122
WidgetState(uint16_t uuid, float x, float y, float w, float h, uint16_t tab)
Definition widget.cpp:13
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:82
static constexpr int hash_count
Definition widget.cpp:120