ravenrs_app/model/
node.rs1use std::collections::BTreeMap;
4
5use serde_json::Value as Json;
6
7#[derive(Clone, Debug, Default, PartialEq)]
9#[cfg_attr(feature = "live", ravenrs_live::expose(part = "fields"))]
10pub struct ModelNode {
11 pub id: String,
13 pub properties: BTreeMap<String, Json>,
15 pub children: Vec<ModelNode>,
17}
18
19#[cfg_attr(feature = "live", ravenrs_live::expose)]
20impl ModelNode {
21 pub fn new(id: impl Into<String>) -> Self {
23 Self { id: id.into(), ..Self::default() }
24 }
25
26 pub fn with(mut self, name: &str, value: impl Into<Json>) -> Self {
28 self.properties.insert(name.to_owned(), value.into());
29 self
30 }
31
32 pub fn child(mut self, child: ModelNode) -> Self {
34 self.children.push(child);
35 self
36 }
37
38 pub(crate) fn in_order_all(&self) -> &[ModelNode] {
40 &self.children
41 }
42
43 pub fn get(&self, id: &str) -> Option<&ModelNode> {
45 self.children.iter().find(|c| c.id == id)
46 }
47
48 pub(crate) fn get_mut(&mut self, id: &str) -> Option<&mut ModelNode> {
49 self.children.iter_mut().find(|c| c.id == id)
50 }
51
52 pub(crate) fn at_mut(&mut self, path: &[&str]) -> Option<&mut ModelNode> {
53 path.iter().try_fold(self, |node, id| node.get_mut(id))
54 }
55
56 pub fn at(&self, path: &[&str]) -> Option<&ModelNode> {
58 path.iter().try_fold(self, |node, id| node.get(id))
59 }
60
61 pub fn text(&self, name: &str) -> Option<&str> {
63 self.properties.get(name).and_then(Json::as_str)
64 }
65
66 pub fn typed(&self, name: &str) -> Option<String> {
68 self.properties.get(name).map(|value| match value {
69 Json::String(text) => text.clone(),
70 other => other.to_string(),
71 })
72 }
73
74 pub fn integer(&self, name: &str) -> Option<i64> {
76 self.properties.get(name).and_then(Json::as_i64)
77 }
78
79 pub fn number(&self, name: &str) -> Option<f64> {
81 self.properties.get(name).and_then(Json::as_f64)
82 }
83
84 pub fn flag(&self, name: &str) -> Option<bool> {
86 self.properties.get(name).and_then(Json::as_bool)
87 }
88
89 pub fn in_order(&self) -> Vec<&ModelNode> {
92 let mut shown: Vec<&ModelNode> =
93 self.children.iter().filter(|c| c.integer("Index").is_none_or(|i| i >= 0)).collect();
94 shown.sort_by_key(|c| c.integer("Index").unwrap_or(i64::MAX));
95 shown
96 }
97}