Skip to main content

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}