9#include <unordered_map>
34 static constexpr uint32_t kInitialWindowCapacity = 16;
35 static constexpr uint32_t kInitialWindowStackCapacity = 8;
60 m_windows.reserve(kInitialWindowCapacity);
61 m_windowStack.reserve(kInitialWindowStackCapacity);
68 for (
auto& window : m_windows)
70 window.members.clear();
71 m_spareMembers.push_back(std::move(window.members));
74 m_windowStack.clear();
75 m_windowIDToIndexMap.clear();
79 uint32_t
WindowCount()
const {
return static_cast<uint32_t
>(m_windows.size()); }
84 if (windowIndex >= m_windows.size())
86 return m_windows[windowIndex].id;
93 return m_windows[windowIndex].windowRef;
99 auto it = m_windowIDToIndexMap.find(
id);
100 if (it == m_windowIDToIndexMap.end())
102 return m_windows[it->second].windowRef;
108 auto it = m_windowIDToIndexMap.find(
id);
109 if (it == m_windowIDToIndexMap.end())
117 auto it = m_windowIDToIndexMap.find(
id);
118 return it != m_windowIDToIndexMap.end();
125 if (windowIndex >= m_windows.size())
return nullptr;
126 return &m_windows[windowIndex].members;
132 return static_cast<uint32_t
>(m_windowStack.size());
144 return !m_windowStack.empty();
154 uint32_t newIndex =
static_cast<uint32_t
>(m_windows.size());
155 std::vector<RenderNode> members;
156 if (!m_spareMembers.empty())
158 members = std::move(m_spareMembers.back());
159 m_spareMembers.pop_back();
164 .parentWindowEntry = m_activeWindowIndex,
167 .members = std::move(members)
169 m_windowIDToIndexMap[id] = newIndex;
172 m_windowStack.push_back(newIndex);
173 m_activeWindowIndex = newIndex;
183 m_windows[m_activeWindowIndex].members.push_back(
RenderNode{ ref, 0, 0 });
191 if (m_windowStack.empty())
return;
192 auto& members = m_windows[m_activeWindowIndex].members;
195 uint32_t nodeStart = UINT32_MAX;
196 for (uint32_t i = 0; i < static_cast<uint32_t>(members.size()); i++)
198 if (members[i].ref == nodeRef) { nodeStart = i;
break; }
200 if (nodeStart == UINT32_MAX)
return;
202 uint32_t nodeDepth = nodeRef.
depth;
205 uint32_t subtreeEnd = nodeStart + 1;
206 while (subtreeEnd < members.size() && members[subtreeEnd].ref.depth > nodeDepth)
211 uint32_t siblingGroupEnd = subtreeEnd;
212 while (siblingGroupEnd < members.size() && members[siblingGroupEnd].ref.depth >= nodeDepth)
216 if (subtreeEnd < siblingGroupEnd)
217 std::rotate(members.begin() + nodeStart, members.begin() + subtreeEnd, members.begin() + siblingGroupEnd);
224 for (
auto& window : m_windows)
226 auto& members = window.members;
228 node.ref = move.
Remap(node.ref);
230 auto isMovedSibling = [&](
const RenderNode& node)
235 auto first = std::find_if(members.begin(), members.end(), isMovedSibling);
236 if (first == members.end())
238 auto last = std::find_if(members.rbegin(), members.rend(), isMovedSibling).base();
239 while (last != members.end() && last->ref.depth > move.
childDepth)
243 struct Chunk { uint32_t index;
size_t begin,
end; };
244 std::vector<Chunk> chunks;
245 for (
auto it = first; it != last; )
250 chunks.push_back({ it->ref.index, size_t(it - members.begin()), size_t(
end - members.begin()) });
253 std::stable_sort(chunks.begin(), chunks.end(), [](
const Chunk& a,
const Chunk& b) { return a.index < b.index; });
255 std::vector<RenderNode> reordered;
256 reordered.reserve(
size_t(last - first));
257 for (
const Chunk& chunk : chunks)
258 reordered.insert(reordered.end(), members.begin() + chunk.begin, members.begin() + chunk.end);
259 std::copy(reordered.begin(), reordered.end(), first);
267 for (
auto& window : m_windows)
269 auto& nodes = window.members;
270 const uint32_t count =
static_cast<uint32_t
>(nodes.size());
272 m_skipLinkStack.clear();
273 for (uint32_t i = 0; i < count; i++)
275 const uint32_t myDepth = nodes[i].ref.depth;
278 while (!m_skipLinkStack.empty() &&
279 nodes[m_skipLinkStack.back()].ref.depth >= myDepth)
281 nodes[m_skipLinkStack.back()].subtreeSkip = i;
282 m_skipLinkStack.pop_back();
284 m_skipLinkStack.push_back(i);
287 for (uint32_t idx : m_skipLinkStack)
288 nodes[idx].subtreeSkip = count;
295 if (m_windowStack.empty())
301 m_windowStack.pop_back();
304 if (!m_windowStack.empty())
306 m_activeWindowIndex = m_windowStack.back();
315 auto begin()
const {
return m_windows.begin(); }
316 auto end()
const {
return m_windows.end(); }
317 const std::vector<WindowEntry>&
Windows()
const {
return m_windows; }
321 std::vector<WindowEntry> m_windows;
322 std::vector<uint32_t> m_windowStack;
323 std::vector<uint32_t> m_skipLinkStack;
324 std::vector<std::vector<RenderNode>> m_spareMembers;
327 std::unordered_map<ID, uint32_t> m_windowIDToIndexMap;
const std::vector< RenderNode > * GetWindowMembers(uint32_t windowIndex) const
A window's render list (nullptr for an invalid index), for building its render data.
Definition gui_window_registry.h:123
uint32_t GetWindowStackDepth() const
How many window scopes are open.
Definition gui_window_registry.h:130
const std::vector< WindowEntry > & Windows() const
The windows, in registration order.
Definition gui_window_registry.h:317
void MoveSubtreeToEnd(const ElementRef &nodeRef)
Moves an element's subtree, in the innermost window scope, to render last among its siblings (on top)...
Definition gui_window_registry.h:189
bool HasActiveWindow() const
True inside a window scope.
Definition gui_window_registry.h:142
uint32_t WindowCount() const
The number of registered windows.
Definition gui_window_registry.h:79
RegistryResult BeginWindowScope(ID id, const ElementRef &ref)
Registers a window element just added to the ElementStorage and opens its scope: following Adds go to...
Definition gui_window_registry.h:149
bool Contains(ID id) const
True when a window with id is registered.
Definition gui_window_registry.h:115
auto end() const
The windows, in registration order.
Definition gui_window_registry.h:316
RegistryResult Add(const ElementRef &ref)
Adds a non-window element to the innermost window scope's render list.
Definition gui_window_registry.h:178
WindowRegistry()
Definition gui_window_registry.h:58
const ID GetWindowID(uint32_t windowIndex) const
The ID of the window at windowIndex; Invalid when out of range.
Definition gui_window_registry.h:82
uint32_t GetWindowIndex(ID id) const
The index of the window with id; kInvalidIndex when unknown.
Definition gui_window_registry.h:106
static constexpr uint32_t kInvalidIndex
Definition gui_window_registry.h:37
ElementRef GetWindowRef(uint32_t windowIndex) const
The element of the window at windowIndex; Invalid when out of range.
Definition gui_window_registry.h:90
void BuildRenderSkipLinks()
Computes subtreeSkip for every RenderNode in every window.
Definition gui_window_registry.h:265
void Clear()
Forgets all windows, keeping capacity; call at BeginConstruction.
Definition gui_window_registry.h:65
ElementRef GetWindowRef(ID id) const
The element of the window with id; Invalid when unknown.
Definition gui_window_registry.h:97
ID GetCurrentWindowID() const
The window being built (innermost window scope); Invalid outside one.
Definition gui_window_registry.h:136
void ApplyElementMove(const ElementMove &move)
Follows the elements an ElementStorage::MoveChild moved: remaps every ref, then reorders the moved si...
Definition gui_window_registry.h:222
RegistryResult EndWindowScope()
Closes the innermost window scope; NoActiveWindow when none is open.
Definition gui_window_registry.h:293
auto begin() const
The windows, in registration order.
Definition gui_window_registry.h:315
@ Success
Definition gui_element_storage.h:44
RegistryResult
Outcome of a WindowRegistry call.
Definition gui_window_registry.h:18
@ InvalidRef
Definition gui_window_registry.h:20
@ Success
Definition gui_window_registry.h:19
@ NoActiveWindow
Definition gui_window_registry.h:21
Definition gui_logging.h:24
What a MoveChild did: the slot rotations it applied at each depth, so code that stores ElementRefs (e...
Definition gui_element.h:162
ElementRef Remap(ElementRef ref) const
Where ref sits after the move.
Definition gui_element.h:170
uint32_t siblingsEnd
Definition gui_element.h:167
uint32_t siblingsBegin
absolute slot range of the siblings that changed order
Definition gui_element.h:166
uint32_t childDepth
depth of the moved siblings
Definition gui_element.h:165
An element's slot in ElementStorage: its depth and index within that depth.
Definition gui_element.h:127
static constexpr ElementRef Invalid()
Definition gui_element.h:135
constexpr bool IsValid() const
Definition gui_element.h:134
uint32_t depth
Definition gui_element.h:128
A 64-bit element ID whose bit layout depends on its IDMode.
Definition gui_id.h:23
static constexpr ID Invalid()
The "no element" ID (all bits zero); also the default for optional ID parameters.
Definition gui_id.h:66
One entry in a window's flat pre-order render list.
Definition gui_window_registry.h:42
uint32_t _pad
explicit padding -> 16 bytes, 4 nodes per cache line
Definition gui_window_registry.h:45
uint32_t subtreeSkip
flat-list index past this subtree
Definition gui_window_registry.h:44
ElementRef ref
Definition gui_window_registry.h:43
A window of this frame and its render list.
Definition gui_window_registry.h:50
ElementRef windowRef
Definition gui_window_registry.h:53
std::vector< RenderNode > members
pre-order, populated during construction
Definition gui_window_registry.h:55
uint32_t parentWindowEntry
index of the enclosing window, if any
Definition gui_window_registry.h:51