microui_redux/widget_tree/node.rs
1//
2// Copyright 2022-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30// -----------------------------------------------------------------------------
31//! Retained node definitions and placement metadata.
32
33use crate::{
34 input::{ContainerOption, WidgetBehaviourOption},
35 layout::{SizePolicy, StackDirection},
36 ContainerHandle, Custom, Id, Node,
37};
38
39use super::{TreeCustomRender, WidgetHandle, WidgetStateHandleDyn};
40
41/// Stable identifier assigned to a retained node.
42pub type NodeId = Id;
43
44/// Placement policy metadata attached to a retained node.
45#[derive(Copy, Clone, Debug, PartialEq)]
46pub struct Policy {
47 /// Width policy associated with the node.
48 pub width: SizePolicy,
49 /// Height policy associated with the node.
50 pub height: SizePolicy,
51}
52
53impl Policy {
54 /// Creates a policy from explicit width and height rules.
55 pub const fn new(width: SizePolicy, height: SizePolicy) -> Self {
56 Self { width, height }
57 }
58
59 /// Uses automatic sizing on both axes.
60 pub const fn auto() -> Self {
61 Self::new(SizePolicy::Auto, SizePolicy::Auto)
62 }
63
64 /// Uses fixed sizing on both axes.
65 pub const fn fixed(width: i32, height: i32) -> Self {
66 Self::new(SizePolicy::Fixed(width), SizePolicy::Fixed(height))
67 }
68
69 /// Uses a fixed width and automatic height.
70 pub const fn fixed_width(width: i32) -> Self {
71 Self::new(SizePolicy::Fixed(width), SizePolicy::Auto)
72 }
73
74 /// Uses a fixed height and automatic width.
75 pub const fn fixed_height(height: i32) -> Self {
76 Self::new(SizePolicy::Auto, SizePolicy::Fixed(height))
77 }
78
79 /// Uses remainder sizing on both axes.
80 pub const fn fill() -> Self {
81 Self::new(SizePolicy::Remainder(0), SizePolicy::Remainder(0))
82 }
83}
84
85/// Kind of a retained node emitted by [`super::WidgetTreeBuilder`].
86pub(crate) enum WidgetTreeNodeKind {
87 /// Leaf node that dispatches widget state through the normal widget pipeline.
88 Widget {
89 /// Retained widget state handle.
90 widget: Box<dyn WidgetStateHandleDyn>,
91 },
92 /// Leaf node that records a deferred custom-render callback.
93 CustomRender {
94 /// Retained widget state handle.
95 state: WidgetHandle<Custom>,
96 /// Deferred rendering callback enqueued after interaction handling.
97 render: TreeCustomRender,
98 },
99 /// Embedded container/panel node with its own child subtree.
100 Container {
101 /// Container handle used for the embedded panel.
102 handle: ContainerHandle,
103 /// Container rendering options.
104 opt: ContainerOption,
105 /// Behaviour options applied while embedded.
106 behaviour: WidgetBehaviourOption,
107 },
108 /// Collapsible header node with optional child content.
109 Header {
110 /// Header state handle that owns the expanded/collapsed state.
111 state: WidgetHandle<Node>,
112 },
113 /// Tree node with automatic indentation while expanded.
114 Tree {
115 /// Tree state handle that owns the expanded/collapsed state.
116 state: WidgetHandle<Node>,
117 },
118 /// Horizontal row flow group.
119 Row {
120 /// Track widths applied to children.
121 widths: Vec<SizePolicy>,
122 /// Shared row height policy.
123 height: SizePolicy,
124 },
125 /// Grid flow group that emits children row-major.
126 Grid {
127 /// Column width policies.
128 widths: Vec<SizePolicy>,
129 /// Row height policies.
130 heights: Vec<SizePolicy>,
131 },
132 /// Nested column scope.
133 Column,
134 /// Vertical stack scope.
135 Stack {
136 /// Width policy applied to each emitted stack item.
137 width: SizePolicy,
138 /// Height policy applied to each emitted stack item.
139 height: SizePolicy,
140 /// Stack direction.
141 direction: StackDirection,
142 },
143}
144
145impl WidgetTreeNodeKind {
146 pub(super) fn tag(&self) -> u8 {
147 match self {
148 Self::Widget { .. } => 1,
149 Self::CustomRender { .. } => 2,
150 Self::Container { .. } => 3,
151 Self::Header { .. } => 4,
152 Self::Tree { .. } => 5,
153 Self::Row { .. } => 6,
154 Self::Grid { .. } => 7,
155 Self::Column => 8,
156 Self::Stack { .. } => 9,
157 }
158 }
159}
160
161/// A single node in a retained widget tree.
162pub struct WidgetTreeNode {
163 pub(super) id: NodeId,
164 pub(super) policy: Policy,
165 pub(super) kind: WidgetTreeNodeKind,
166 pub(super) children: Vec<WidgetTreeNode>,
167}
168
169impl WidgetTreeNode {
170 /// Returns the stable node identifier.
171 pub fn id(&self) -> NodeId {
172 self.id
173 }
174
175 /// Returns the node's policy metadata.
176 pub fn policy(&self) -> Policy {
177 self.policy
178 }
179
180 /// Returns the node kind.
181 #[cfg(test)]
182 pub(crate) fn kind(&self) -> &WidgetTreeNodeKind {
183 &self.kind
184 }
185
186 /// Returns the node's child nodes.
187 pub fn children(&self) -> &[WidgetTreeNode] {
188 &self.children
189 }
190
191 pub(crate) fn parts(&self) -> (NodeId, &WidgetTreeNodeKind, &[WidgetTreeNode]) {
192 (self.id, &self.kind, &self.children)
193 }
194}
195
196/// Completed retained widget tree.
197#[derive(Default)]
198pub struct WidgetTree {
199 pub(super) roots: Vec<WidgetTreeNode>,
200}
201
202impl WidgetTree {
203 /// Returns the root nodes of the tree.
204 pub fn roots(&self) -> &[WidgetTreeNode] {
205 &self.roots
206 }
207}