载入中...
搜索中...
未找到
Widget.cpp
浏览该文件的文档.
1#include "ui/Widget.h"
2
3namespace eve::ui {
4namespace {
5
6int appendNode(UIHost::Tree &tree, WidgetDesc &&desc, int parent = -1) {
7 const int index = int(tree.nodes.size());
8 UINode node;
9 node.type = desc.type;
10 node.id = std::move(desc.id);
11 node.key = desc.key.empty() ? node.id : std::move(desc.key);
12 node.text = std::move(desc.text);
13 node.valueText = std::move(desc.valueText);
14 node.tooltip = std::move(desc.tooltip);
15 node.visible = desc.visible;
16 node.enabled = desc.enabled;
17 node.checked = desc.checked;
18 node.open = desc.open;
19 node.focusMode = desc.focusMode;
20 node.mouseFilter = desc.mouseFilter;
21 node.themePreset = desc.themePreset;
22 node.styleClass = std::move(desc.styleClass);
23 node.hasResolvedStyle =
24 resolveStyleClass(node.styleClass, &node.resolvedStyle) == StyleClassStatus::Applied;
25 node.tabIndex = desc.tabIndex;
26 node.focusNext = std::move(desc.focusNext);
27 node.focusPrevious = std::move(desc.focusPrevious);
28 node.focusLeft = std::move(desc.focusLeft);
29 node.focusRight = std::move(desc.focusRight);
30 node.focusUp = std::move(desc.focusUp);
31 node.focusDown = std::move(desc.focusDown);
32 node.accessibilityRole = desc.accessibilityRole;
33 node.accessibilityName = std::move(desc.accessibilityName);
34 node.accessibilityDescription = std::move(desc.accessibilityDescription);
35 node.dragSource = desc.dragSource;
36 node.dropTarget = desc.dropTarget;
37 node.dragPayloadType = std::move(desc.dragPayloadType);
38 node.dragPayloadText = std::move(desc.dragPayloadText);
39 node.acceptedDropType = std::move(desc.acceptedDropType);
40 node.value = desc.value;
41 node.minValue = desc.minValue;
42 node.maxValue = desc.maxValue;
43 node.sizeX = desc.sizeX;
44 node.sizeY = desc.sizeY;
45 node.marginL = desc.marginL;
46 node.marginT = desc.marginT;
47 node.marginR = desc.marginR;
48 node.marginB = desc.marginB;
49 node.paddingL = desc.paddingL;
50 node.paddingT = desc.paddingT;
51 node.paddingR = desc.paddingR;
52 node.paddingB = desc.paddingB;
53 node.minSizeX = desc.minSizeX;
54 node.minSizeY = desc.minSizeY;
55 node.maxSizeX = desc.maxSizeX;
56 node.maxSizeY = desc.maxSizeY;
57 node.percentW = desc.percentW;
58 node.percentH = desc.percentH;
59 node.aspectRatio = desc.aspectRatio;
60 node.anchorX = desc.anchorX;
61 node.anchorY = desc.anchorY;
62 node.posX = desc.posX;
63 node.posY = desc.posY;
64 node.absolute = desc.absolute;
65 node.textureId = desc.textureId;
66 node.tintR = desc.tintR;
67 node.tintG = desc.tintG;
68 node.tintB = desc.tintB;
69 node.tintA = desc.tintA;
70 node.uv0x = desc.uv0x;
71 node.uv0y = desc.uv0y;
72 node.uv1x = desc.uv1x;
73 node.uv1y = desc.uv1y;
74 node.borderL = desc.borderL;
75 node.borderT = desc.borderT;
76 node.borderR = desc.borderR;
77 node.borderB = desc.borderB;
78 node.cornerRadius = desc.cornerRadius;
79 node.wrapWidth = desc.wrapWidth;
80 node.itemHeight = desc.itemHeight;
81 node.flexDirection = desc.flexDirection;
82 node.alignItems = desc.alignItems;
83 node.justifyContent = desc.justifyContent;
84 node.gap = desc.gap;
85 node.flexGrow = desc.flexGrow;
86 node.flexShrink = desc.flexShrink;
87 node.flexBasis = desc.flexBasis;
88 node.alignSelf = desc.alignSelf;
89 node.columnGap = desc.columnGap;
90 node.rowGap = desc.rowGap;
91 node.flexWrap = desc.flexWrap;
92 node.overflow = desc.overflow;
93 node.gridColumns = desc.gridColumns;
94 node.gridColumnSpan = desc.gridColumnSpan;
95 node.parent = parent;
96 node.firstChild = -1;
97 node.nextSibling = -1;
98 node.handlerClick = 0;
99 node.handlerToggle = 0;
100 node.handlerValue = 0;
101 node.handlerText = 0;
102
103 if (desc.onClick) {
104 tree.clickHandlers.push_back(std::move(desc.onClick));
105 node.handlerClick = static_cast<uint32_t>(tree.clickHandlers.size());
106 }
107 if (desc.onToggle) {
108 tree.toggleHandlers.push_back(std::move(desc.onToggle));
109 node.handlerToggle = static_cast<uint32_t>(tree.toggleHandlers.size());
110 }
111 if (desc.onValue) {
112 tree.valueHandlers.push_back(std::move(desc.onValue));
113 node.handlerValue = static_cast<uint32_t>(tree.valueHandlers.size());
114 }
115 if (desc.onTextChange) {
116 tree.textHandlers.push_back(std::move(desc.onTextChange));
117 node.handlerText = static_cast<uint32_t>(tree.textHandlers.size());
118 }
119
120 tree.nodes.push_back(std::move(node));
121
122 int prevChild = -1;
123 int firstChild = -1;
124 for (auto &child : desc.children) {
125 int childIndex = appendNode(tree, std::move(child), index);
126 if (firstChild < 0) firstChild = childIndex;
127 if (prevChild >= 0) tree.nodes[size_t(prevChild)].nextSibling = childIndex;
128 prevChild = childIndex;
129 }
130 tree.nodes[size_t(index)].firstChild = firstChild;
131 return index;
132}
133
134bool structureMatches(const UIHost::Tree &tree, int nodeIndex, const WidgetDesc &desc) {
135 if (nodeIndex < 0 || nodeIndex >= int(tree.nodes.size())) return false;
136 const UINode &n = tree.nodes[size_t(nodeIndex)];
137 if (n.type != desc.type) return false;
138 const std::string &dk = desc.reconcileKey();
139 if (!dk.empty() && !n.key.empty() && n.key != dk) return false;
140
141 std::vector<std::string> oldKeys;
142 for (int c = n.firstChild; c >= 0; c = tree.nodes[size_t(c)].nextSibling) {
143 oldKeys.push_back(tree.nodes[size_t(c)].key);
144 }
145 if (oldKeys.size() != desc.children.size()) return false;
146 for (size_t i = 0; i < desc.children.size(); ++i) {
147 const std::string &ck = desc.children[i].reconcileKey();
148 if (ck.empty() || oldKeys[i].empty()) {
149 if (!(ck.empty() && oldKeys[i].empty())) return false;
150 } else if (ck != oldKeys[i]) {
151 return false;
152 }
153 }
154
155 int child = n.firstChild;
156 for (const auto &ch : desc.children) {
157 if (!structureMatches(tree, child, ch)) return false;
158 child = tree.nodes[size_t(child)].nextSibling;
159 }
160 return true;
161}
162
163void patchProps(UIHost::Tree &tree, int nodeIndex, WidgetDesc &&desc) {
164 UINode &n = tree.nodes[size_t(nodeIndex)];
165 n.text = std::move(desc.text);
166 n.valueText = std::move(desc.valueText);
167 n.tooltip = std::move(desc.tooltip);
168 n.visible = desc.visible;
169 n.enabled = desc.enabled;
170 n.checked = desc.checked;
171 n.open = desc.open;
172 n.focusMode = desc.focusMode;
173 n.mouseFilter = desc.mouseFilter;
174 n.themePreset = desc.themePreset;
175 n.styleClass = std::move(desc.styleClass);
176 n.hasResolvedStyle =
177 resolveStyleClass(n.styleClass, &n.resolvedStyle) == StyleClassStatus::Applied;
178 n.tabIndex = desc.tabIndex;
179 n.focusNext = std::move(desc.focusNext);
180 n.focusPrevious = std::move(desc.focusPrevious);
181 n.focusLeft = std::move(desc.focusLeft);
182 n.focusRight = std::move(desc.focusRight);
183 n.focusUp = std::move(desc.focusUp);
184 n.focusDown = std::move(desc.focusDown);
185 n.accessibilityRole = desc.accessibilityRole;
186 n.accessibilityName = std::move(desc.accessibilityName);
187 n.accessibilityDescription = std::move(desc.accessibilityDescription);
188 n.dragSource = desc.dragSource;
189 n.dropTarget = desc.dropTarget;
190 n.dragPayloadType = std::move(desc.dragPayloadType);
191 n.dragPayloadText = std::move(desc.dragPayloadText);
192 n.acceptedDropType = std::move(desc.acceptedDropType);
193 n.value = desc.value;
194 n.minValue = desc.minValue;
195 n.maxValue = desc.maxValue;
196 n.sizeX = desc.sizeX;
197 n.sizeY = desc.sizeY;
198 n.marginL = desc.marginL;
199 n.marginT = desc.marginT;
200 n.marginR = desc.marginR;
201 n.marginB = desc.marginB;
202 n.paddingL = desc.paddingL;
203 n.paddingT = desc.paddingT;
204 n.paddingR = desc.paddingR;
205 n.paddingB = desc.paddingB;
206 n.minSizeX = desc.minSizeX;
207 n.minSizeY = desc.minSizeY;
208 n.maxSizeX = desc.maxSizeX;
209 n.maxSizeY = desc.maxSizeY;
210 n.percentW = desc.percentW;
211 n.percentH = desc.percentH;
212 n.aspectRatio = desc.aspectRatio;
213 n.anchorX = desc.anchorX;
214 n.anchorY = desc.anchorY;
215 n.posX = desc.posX;
216 n.posY = desc.posY;
217 n.absolute = desc.absolute;
218 n.textureId = desc.textureId;
219 n.tintR = desc.tintR;
220 n.tintG = desc.tintG;
221 n.tintB = desc.tintB;
222 n.tintA = desc.tintA;
223 n.uv0x = desc.uv0x;
224 n.uv0y = desc.uv0y;
225 n.uv1x = desc.uv1x;
226 n.uv1y = desc.uv1y;
227 n.borderL = desc.borderL;
228 n.borderT = desc.borderT;
229 n.borderR = desc.borderR;
230 n.borderB = desc.borderB;
231 n.cornerRadius = desc.cornerRadius;
232 n.wrapWidth = desc.wrapWidth;
233 n.itemHeight = desc.itemHeight;
234 n.flexDirection = desc.flexDirection;
235 n.alignItems = desc.alignItems;
236 n.justifyContent = desc.justifyContent;
237 n.gap = desc.gap;
238 n.flexGrow = desc.flexGrow;
239 n.flexShrink = desc.flexShrink;
240 n.flexBasis = desc.flexBasis;
241 n.alignSelf = desc.alignSelf;
242 n.columnGap = desc.columnGap;
243 n.rowGap = desc.rowGap;
244 n.flexWrap = desc.flexWrap;
245 n.overflow = desc.overflow;
246 n.gridColumns = desc.gridColumns;
247 n.gridColumnSpan = desc.gridColumnSpan;
248 if (!desc.id.empty()) n.id = desc.id;
249
250 if (desc.onClick) {
251 if (n.handlerClick != 0) {
252 tree.clickHandlers[size_t(n.handlerClick - 1)] = std::move(desc.onClick);
253 } else {
254 tree.clickHandlers.push_back(std::move(desc.onClick));
255 n.handlerClick = static_cast<uint32_t>(tree.clickHandlers.size());
256 }
257 }
258 if (desc.onToggle) {
259 if (n.handlerToggle != 0) {
260 tree.toggleHandlers[size_t(n.handlerToggle - 1)] = std::move(desc.onToggle);
261 } else {
262 tree.toggleHandlers.push_back(std::move(desc.onToggle));
263 n.handlerToggle = static_cast<uint32_t>(tree.toggleHandlers.size());
264 }
265 }
266 if (desc.onValue) {
267 if (n.handlerValue != 0) {
268 tree.valueHandlers[size_t(n.handlerValue - 1)] = std::move(desc.onValue);
269 } else {
270 tree.valueHandlers.push_back(std::move(desc.onValue));
271 n.handlerValue = static_cast<uint32_t>(tree.valueHandlers.size());
272 }
273 }
274 if (desc.onTextChange) {
275 if (n.handlerText != 0) {
276 tree.textHandlers[size_t(n.handlerText - 1)] = std::move(desc.onTextChange);
277 } else {
278 tree.textHandlers.push_back(std::move(desc.onTextChange));
279 n.handlerText = static_cast<uint32_t>(tree.textHandlers.size());
280 }
281 }
282
283 int child = n.firstChild;
284 for (auto &ch : desc.children) {
285 patchProps(tree, child, std::move(ch));
286 child = tree.nodes[size_t(child)].nextSibling;
287 }
288}
289
290} // namespace
291
292WidgetDesc window(std::string title, std::vector<WidgetDesc> children, std::string id) {
295 d.id = std::move(id);
296 d.key = d.id;
297 d.text = std::move(title);
298 d.children = std::move(children);
299 return d;
300}
301
302WidgetDesc text(std::string content, std::string id) {
305 d.id = std::move(id);
306 d.key = d.id;
307 d.text = std::move(content);
308 return d;
309}
310
311WidgetDesc button(std::string label, std::string id, std::function<void()> onClick) {
314 d.id = std::move(id);
315 d.key = d.id;
316 d.text = std::move(label);
317 d.onClick = std::move(onClick);
318 return d;
319}
320
321WidgetDesc icon(Icon value, std::string id) { return text(iconGlyph(value), std::move(id)); }
322
323WidgetDesc iconButton(Icon value, std::string label, std::string id,
324 std::function<void()> onClick) {
325 return button(iconText(value, label), std::move(id), std::move(onClick));
326}
327
328WidgetDesc group(std::vector<WidgetDesc> children, std::string id) {
331 d.id = std::move(id);
332 d.key = d.id;
333 d.children = std::move(children);
334 return d;
335}
336
337WidgetDesc sameLine(std::string id) {
340 d.id = std::move(id);
341 d.key = d.id;
342 return d;
343}
344
345WidgetDesc separator(std::string id) {
348 d.id = std::move(id);
349 d.key = d.id;
350 return d;
351}
352
353WidgetDesc checkbox(std::string label, bool checked, std::string id,
354 std::function<void(bool)> onToggle) {
357 d.id = std::move(id);
358 d.key = d.id;
359 d.text = std::move(label);
360 d.checked = checked;
361 d.onToggle = std::move(onToggle);
362 return d;
363}
364
365WidgetDesc slider(std::string label, float value, float minV, float maxV, std::string id,
366 std::function<void(float)> onValue) {
369 d.id = std::move(id);
370 d.key = d.id;
371 d.text = std::move(label);
372 d.value = value;
373 d.minValue = minV;
374 d.maxValue = maxV;
375 d.onValue = std::move(onValue);
376 return d;
377}
378
379WidgetDesc colorPalette(std::string label, float r, float g, float b, float a, std::string id,
380 std::function<void(float)> onValue) {
383 d.id = std::move(id);
384 d.key = d.id;
385 d.text = std::move(label);
386 d.tintR = r;
387 d.tintG = g;
388 d.tintB = b;
389 d.tintA = a;
390 d.accessibilityRole = AccessibilityRole::Slider;
391 d.onValue = std::move(onValue);
392 return d;
393}
394
395WidgetDesc progress(float fraction, std::string id, std::string overlay) {
398 d.id = std::move(id);
399 d.key = d.id;
400 d.value = fraction;
401 d.text = std::move(overlay);
402 return d;
403}
404
405WidgetDesc combo(std::string label, std::vector<std::string> options, int selected,
406 std::string id, std::function<void(float)> onValue) {
409 d.id = std::move(id);
410 d.key = d.id;
411 d.text = std::move(label);
412 d.value = float(std::max(0, selected));
413 for (size_t i = 0; i < options.size(); ++i) {
414 if (i) d.valueText += '\n';
415 d.valueText += options[i];
416 }
417 d.onValue = std::move(onValue);
418 return d;
419}
420
421WidgetDesc image(std::string id, float width, float height, std::function<void()> onClick) {
424 d.id = std::move(id);
425 d.key = d.id;
426 d.sizeX = width;
427 d.sizeY = height;
428 d.onClick = std::move(onClick);
429 return d;
430}
431
432WidgetDesc imageButton(std::string id, float width, float height, std::function<void()> onClick) {
435 d.id = std::move(id);
436 d.key = d.id;
437 d.sizeX = width;
438 d.sizeY = height;
439 d.onClick = std::move(onClick);
440 return d;
441}
442
443WidgetDesc viewport(std::string id, float width, float height) {
446 d.id = std::move(id);
447 d.key = d.id;
448 d.sizeX = width;
449 d.sizeY = height;
450 return d;
451}
452
453WidgetDesc inputText(std::string label, std::string value, std::string id,
454 std::function<void(const std::string &)> onChange) {
457 d.id = std::move(id);
458 d.key = d.id;
459 d.text = std::move(label);
460 d.valueText = std::move(value);
461 d.onTextChange = std::move(onChange);
462 return d;
463}
464
465WidgetDesc searchField(std::string hint, std::string value, std::string id,
466 std::function<void(const std::string &)> onChange) {
469 d.id = std::move(id);
470 d.key = d.id;
471 d.text = std::move(hint);
472 d.valueText = std::move(value);
473 d.onTextChange = std::move(onChange);
474 return d;
475}
476
477WidgetDesc toggleSwitch(std::string label, bool checked, std::string id,
478 std::function<void(bool)> onToggle) {
481 d.id = std::move(id);
482 d.key = d.id;
483 d.text = std::move(label);
484 d.checked = checked;
485 d.onToggle = std::move(onToggle);
486 return d;
487}
488
489WidgetDesc badge(std::string label, std::string id) {
492 d.id = std::move(id);
493 d.key = d.id;
494 d.text = std::move(label);
495 d.tintR = 0.96f;
496 d.tintG = 0.35f;
497 d.tintB = 0.40f;
498 d.tintA = 0.20f;
499 return d;
500}
501
502WidgetDesc card(std::vector<WidgetDesc> children, std::string id) {
505 d.id = std::move(id);
506 d.key = d.id;
507 d.children = std::move(children);
508 return d;
509}
510
511WidgetDesc ninePatchPanel(std::vector<WidgetDesc> children, std::string id,
512 uint64_t textureId) {
515 d.id = std::move(id);
516 d.key = d.id;
517 d.textureId = textureId;
518 d.children = std::move(children);
519 return d;
520}
521
522WidgetDesc sectionHeader(std::string label, std::string id) {
525 d.id = std::move(id);
526 d.key = d.id;
527 d.text = std::move(label);
528 return d;
529}
530
531WidgetDesc menuBar(std::vector<WidgetDesc> children, std::string id) {
534 d.id = std::move(id);
535 d.key = d.id;
536 d.children = std::move(children);
537 return d;
538}
539
540WidgetDesc menu(std::string label, std::vector<WidgetDesc> children, std::string id) {
543 d.id = std::move(id);
544 d.key = d.id;
545 d.text = std::move(label);
546 d.children = std::move(children);
547 return d;
548}
549
550WidgetDesc menuItem(std::string label, std::string shortcut, std::string id,
551 std::function<void()> onClick, bool selected) {
554 d.id = std::move(id);
555 d.key = d.id;
556 d.text = std::move(label);
557 d.valueText = std::move(shortcut);
558 d.checked = selected;
559 d.onClick = std::move(onClick);
560 return d;
561}
562
563WidgetDesc toolbar(std::vector<WidgetDesc> children, std::string id) {
566 d.id = std::move(id);
567 d.key = d.id;
568 d.flexDirection = FlexDirection::Row;
569 d.alignItems = FlexAlign::Center;
570 d.children = std::move(children);
571 return d;
572}
573
574WidgetDesc toolbox(std::vector<WidgetDesc> children, std::string id, float cellSize,
575 int columns) {
578 d.id = std::move(id);
579 d.key = d.id;
580 d.itemHeight = cellSize > 0.f ? cellSize : 40.f;
581 d.value = float(std::max(0, columns));
582 d.children = std::move(children);
583 return d;
584}
585
586WidgetDesc sidebar(std::vector<WidgetDesc> children, std::string id, float width) {
589 d.id = std::move(id);
590 d.key = d.id;
591 d.sizeX = width;
592 d.children = std::move(children);
593 return d;
594}
595
596WidgetDesc statusBar(std::vector<WidgetDesc> children, std::string id) {
599 d.id = std::move(id);
600 d.key = d.id;
601 d.flexDirection = FlexDirection::Row;
602 d.alignItems = FlexAlign::Center;
603 d.children = std::move(children);
604 return d;
605}
606
608 std::string id, std::function<void(float)> onResize) {
611 d.id = std::move(id);
612 d.key = d.id;
613 d.flexDirection = direction;
614 d.value = std::max(0.1f, std::min(0.9f, ratio));
615 d.minValue = 0.1f;
616 d.maxValue = 0.9f;
617 d.onValue = std::move(onResize);
618 d.children.push_back(std::move(first));
619 d.children.push_back(std::move(second));
620 return d;
621}
622
623WidgetDesc collapsingHeader(std::string label, std::vector<WidgetDesc> children, std::string id,
624 bool defaultOpen) {
627 d.id = std::move(id);
628 d.key = d.id;
629 d.text = std::move(label);
630 d.open = defaultOpen;
631 d.children = std::move(children);
632 return d;
633}
634
635WidgetDesc child(std::string id, std::vector<WidgetDesc> children, float width, float height) {
638 d.id = std::move(id);
639 d.key = d.id;
640 d.sizeX = width;
641 d.sizeY = height;
642 d.children = std::move(children);
643 return d;
644}
645
646WidgetDesc scrollList(std::string id, std::vector<WidgetDesc> children, float height,
647 float itemHeight) {
650 d.id = std::move(id);
651 d.key = d.id;
652 d.sizeY = height;
653 d.itemHeight = itemHeight;
654 d.children = std::move(children);
655 return d;
656}
657
658WidgetDesc virtualList(std::string listId, const std::vector<std::string> &items, float height,
659 float itemHeight) {
660 const std::string lid = listId;
661 WidgetDesc inner = list(std::move(listId), items,
662 [lid](const std::string &label, int i) {
663 return button(label, lid + "/" + std::to_string(i))
664 .withKey(lid + "/" + std::to_string(i));
665 });
666 return scrollList(lid, std::move(inner.children), height, itemHeight);
667}
668
669WidgetDesc flex(FlexDirection direction, std::vector<WidgetDesc> children, std::string id) {
672 d.id = std::move(id);
673 d.key = d.id;
674 d.flexDirection = direction;
675 d.children = std::move(children);
676 return d;
677}
678
679WidgetDesc row(std::vector<WidgetDesc> children, std::string id) {
680 return flex(FlexDirection::Row, std::move(children), std::move(id));
681}
682
683WidgetDesc column(std::vector<WidgetDesc> children, std::string id) {
684 return flex(FlexDirection::Column, std::move(children), std::move(id));
685}
686
687WidgetDesc grid(int columns, std::vector<WidgetDesc> children, std::string id) {
690 d.id = std::move(id);
691 d.key = d.id;
692 d.gridColumns = std::max(1, columns);
693 d.children = std::move(children);
694 return d;
695}
696
697WidgetDesc spacer(std::string id, float grow) {
700 d.id = std::move(id);
701 d.key = d.id;
702 d.flexGrow = grow > 0.f ? grow : 1.f;
703 return d;
704}
705
707 if (!cond) return group({}, "__when_empty");
708 return child;
709}
710
711WidgetDesc whenElse(bool cond, WidgetDesc ifTrue, WidgetDesc ifFalse) {
712 return cond ? std::move(ifTrue) : std::move(ifFalse);
713}
714
715WidgetDesc list(std::string listId, const std::vector<std::string> &items,
716 const std::function<WidgetDesc(const std::string &, int)> &itemFn) {
717 std::vector<WidgetDesc> children;
718 children.reserve(items.size());
719 for (int i = 0; i < int(items.size()); ++i) {
720 WidgetDesc row = itemFn(items[size_t(i)], i);
721 if (row.id.empty()) row.id = listId + "/" + std::to_string(i);
722 if (row.key.empty()) row.key = row.id;
723 children.push_back(std::move(row));
724 }
725 return group(std::move(children), std::move(listId));
726}
727
728WidgetDesc listButtons(std::string listId, const std::vector<std::string> &items) {
729 std::string lid = listId;
730 return list(std::move(listId), items, [lid](const std::string &label, int i) {
731 return button(label, lid + "/" + std::to_string(i)).withKey(lid + "/" + std::to_string(i));
732 });
733}
734
736 if (!host) return;
737 auto t = host->tree();
738 t->nodes.clear();
739 t->clickHandlers.clear();
740 t->toggleHandlers.clear();
741 t->valueHandlers.clear();
742 t->textHandlers.clear();
743 t->root = -1;
744 t->root = appendNode(*t, std::move(root));
745 t->dirty = true;
746}
747
749 if (!host) return true;
750 auto t = host->tree();
751 if (t->root < 0 || t->nodes.empty() || !structureMatches(*t, t->root, root)) {
752 applyTree(host, std::move(root));
753 return true;
754 }
755 patchProps(*t, t->root, std::move(root));
756 t->dirty = false;
757 return false;
758}
759
760} // namespace eve::ui
double value
int root
Definition AnimSmr.cpp:119
building::EdgeCurveGroup group
std::string title
std::string label
int column
scene::NodeDesc desc
tensor::Graph g
Definition GpuGraph.cpp:7
vk::UniqueImage image
glm::vec3 n
Definition Grass.cpp:63
double r
std::int32_t second
std::int32_t c
std::int32_t first
Icon icon
Definition Icons.cpp:11
std::uint32_t height
std::uint32_t width
std::string text
std::int32_t parent
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float d
float t
const RoadNode * node
RoadLaneDirection direction
const SquirrelValueOptions & options
int columns
int children
Definition TreeMesh.cpp:295
UIHostHandle host
uint32_t index
ECS mount point for one UI panel/screen. Subclass to attach UI to game entities, e....
Definition UIHost.h:243
WidgetDesc collapsingHeader(std::string label, std::vector< WidgetDesc > children, std::string id, bool defaultOpen)
Collapsible header containing child widgets.
Definition Widget.cpp:623
const char * iconGlyph(Icon icon)
Returns the UTF-8 glyph for an icon, or an empty string for None.
Definition Icons.cpp:86
WidgetDesc menuItem(std::string label, std::string shortcut, std::string id, std::function< void()> onClick, bool selected)
Selectable menu command with an optional shortcut hint.
Definition Widget.cpp:550
WidgetDesc badge(std::string label, std::string id)
Compact status/category pill. Tint controls its background color.
Definition Widget.cpp:489
WidgetDesc checkbox(std::string label, bool checked, std::string id, std::function< void(bool)> onToggle)
Checkbox with a label; fires onToggle.
Definition Widget.cpp:353
Icon
Semantic editor icons backed by the bundled Font Awesome 4.7 font.
Definition Icons.h:11
std::string iconText(Icon icon, std::string_view label)
Composes an icon with an optional visible label.
Definition Icons.cpp:101
WidgetDesc combo(std::string label, std::vector< std::string > options, int selected, std::string id, std::function< void(float)> onValue)
Combo.
Definition Widget.cpp:405
WidgetDesc statusBar(std::vector< WidgetDesc > children, std::string id)
Compact horizontal status strip; Spacer children absorb free width.
Definition Widget.cpp:596
WidgetDesc slider(std::string label, float value, float minV, float maxV, std::string id, std::function< void(float)> onValue)
Horizontal slider; fires onValue.
Definition Widget.cpp:365
void applyTree(UIHost *host, WidgetDesc root)
Full replace flatten.
Definition Widget.cpp:735
FlexDirection
Main-axis direction for Flex containers.
Definition UIHost.h:58
WidgetDesc whenElse(bool cond, WidgetDesc ifTrue, WidgetDesc ifFalse)
When else.
Definition Widget.cpp:711
WidgetDesc imageButton(std::string id, float width, float height, std::function< void()> onClick)
Image button.
Definition Widget.cpp:432
WidgetDesc inputText(std::string label, std::string value, std::string id, std::function< void(const std::string &)> onChange)
Editable text field; fires onTextChange.
Definition Widget.cpp:453
WidgetDesc window(std::string title, std::vector< WidgetDesc > children, std::string id)
Top-level window widget with a title bar.
Definition Widget.cpp:292
WidgetDesc spacer(std::string id, float grow)
Flexible empty space; default flexGrow=1 so it absorbs free space in a Flex parent.
Definition Widget.cpp:697
WidgetDesc child(std::string id, std::vector< WidgetDesc > children, float width, float height)
Scrollable child region with an explicit size.
Definition Widget.cpp:635
WidgetDesc when(bool cond, WidgetDesc child)
Conditional: include child only when cond is true (empty group otherwise).
Definition Widget.cpp:706
WidgetDesc toolbar(std::vector< WidgetDesc > children, std::string id)
Horizontal editor command strip; Spacer children absorb free width.
Definition Widget.cpp:563
WidgetDesc menu(std::string label, std::vector< WidgetDesc > children, std::string id)
Popup menu container used inside a MenuBar or another Menu.
Definition Widget.cpp:540
WidgetDesc progress(float fraction, std::string id, std::string overlay)
Progress bar; fraction is clamped to [0,1].
Definition Widget.cpp:395
WidgetDesc colorPalette(std::string label, float r, float g, float b, float a, std::string id, std::function< void(float)> onValue)
Color editor with a swatch grid (调色板). RGBA is stored in tint channels. valueText may list extra swat...
Definition Widget.cpp:379
WidgetDesc ninePatchPanel(std::vector< WidgetDesc > children, std::string id, uint64_t textureId)
Stretchable textured container with asset-defined content padding.
Definition Widget.cpp:511
WidgetDesc iconButton(Icon value, std::string label, std::string id, std::function< void()> onClick)
Button containing a semantic icon and optional visible label.
Definition Widget.cpp:323
WidgetDesc grid(int columns, std::vector< WidgetDesc > children, std::string id)
Fixed-column grid; children are placed in source order.
Definition Widget.cpp:687
WidgetDesc listButtons(std::string listId, const std::vector< std::string > &items)
Default list: one Button per item, id = listId + "/" + index.
Definition Widget.cpp:728
WidgetDesc viewport(std::string id, float width, float height)
Viewport.
Definition Widget.cpp:443
WidgetDesc searchField(std::string hint, std::string value, std::string id, std::function< void(const std::string &)> onChange)
Compact search field with placeholder text and a bundled search icon.
Definition Widget.cpp:465
WidgetDesc button(std::string label, std::string id, std::function< void()> onClick)
Clickable button; fires onClick.
Definition Widget.cpp:311
WidgetDesc flex(FlexDirection direction, std::vector< WidgetDesc > children, std::string id)
Elastic layout container (row/column). Prefer row / column shorthands.
Definition Widget.cpp:669
WidgetDesc toggleSwitch(std::string label, bool checked, std::string id, std::function< void(bool)> onToggle)
Modern boolean toggle; fires onToggle when changed.
Definition Widget.cpp:477
WidgetDesc sidebar(std::vector< WidgetDesc > children, std::string id, float width)
Vertical editor side panel. Width defaults to 240 logical pixels.
Definition Widget.cpp:586
StyleClassStatus resolveStyleClass(const std::string &name, StyleClass *out)
Resolves inheritance into a sparse class and reports an explicit lookup status.
Definition Theme.cpp:150
WidgetDesc card(std::vector< WidgetDesc > children, std::string id)
Bordered surface container with editor-friendly padding.
Definition Widget.cpp:502
bool applyTreeReconcile(UIHost *host, WidgetDesc root)
Patch by key/id when structure (type + child keys) matches; otherwise full replace....
Definition Widget.cpp:748
WidgetDesc row(std::vector< WidgetDesc > children, std::string id)
Horizontal elastic layout row.
Definition Widget.cpp:679
WidgetDesc virtualList(std::string listId, const std::vector< std::string > &items, float height, float itemHeight)
Virtual list.
Definition Widget.cpp:658
WidgetDesc toolbox(std::vector< WidgetDesc > children, std::string id, float cellSize, int columns)
Wrapping grid of editor tools with uniform square cells.
Definition Widget.cpp:574
WidgetDesc scrollList(std::string id, std::vector< WidgetDesc > children, float height, float itemHeight)
Scroll list.
Definition Widget.cpp:646
WidgetDesc splitPane(FlexDirection direction, WidgetDesc first, WidgetDesc second, float ratio, std::string id, std::function< void(float)> onResize)
Two resizable panes separated by a drag handle.
Definition Widget.cpp:607
WidgetDesc sectionHeader(std::string label, std::string id)
Non-collapsible editor section heading with an accent marker.
Definition Widget.cpp:522
WidgetDesc separator(std::string id)
Horizontal separator line.
Definition Widget.cpp:345
WidgetDesc sameLine(std::string id)
Holds the next widget on the same line as the previous one.
Definition Widget.cpp:337
WidgetDesc list(std::string listId, const std::vector< std::string > &items, const std::function< WidgetDesc(const std::string &, int)> &itemFn)
Expand a string list into a Group of item widgets. itemFn(label, index) builds each row; keys default...
Definition Widget.cpp:715
WidgetDesc menuBar(std::vector< WidgetDesc > children, std::string id)
Window menu bar container. Must be a direct child of a Window.
Definition Widget.cpp:531
Declarative widget description (build once / on dirty → flatten into UIHost::Tree).
Definition Widget.h:15
std::vector< WidgetDesc > children
Definition Widget.h:111
NodeType type
Definition Widget.h:16
std::string key
Reconciliation key; defaults to id when empty.
Definition Widget.h:19
std::string text
Definition Widget.h:20
WidgetDesc & withKey(std::string v)
With key.
Definition Widget.h:119
std::string id
Definition Widget.h:17