Skip to main content

ferroui_base/rendering/composition/server/
server_list.rs

1use super::{IServerObject, ServerCompositor};
2use crate::rendering::composition::transport::BatchStreamReader;
3use std::cell::RefCell;
4use std::rc::Rc;
5
6/// A server-side list container capable of receiving changes from the UI
7/// thread. Right now it's quite dumb since it always receives the full
8/// list.
9///
10/// Embedded by the generated property block of a list class; the items are
11/// the server objects the batch names.
12#[derive(Default)]
13pub struct ServerList {
14    list: RefCell<Vec<Rc<dyn IServerObject>>>,
15}
16
17impl ServerList {
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    /// A snapshot of the items.
23    pub fn list(&self) -> Vec<Rc<dyn IServerObject>> {
24        self.list.borrow().clone()
25    }
26
27    /// Drops the items.
28    pub fn clear(&self) {
29        self.list.borrow_mut().clear();
30    }
31
32    pub fn count(&self) -> usize {
33        self.list.borrow().len()
34    }
35
36    /// The items viewed as their concrete type. Panics if an item is of
37    /// another type.
38    pub fn items<T: IServerObject>(&self) -> Vec<Rc<T>> {
39        self.list
40            .borrow()
41            .iter()
42            .map(|item| match item.clone().into_any_rc().downcast::<T>() {
43                Ok(item) => item,
44                Err(_) => panic!("a server list holds an item of another type"),
45            })
46            .collect()
47    }
48
49    /// Reads the list part of the changes of the object. The changes of the
50    /// base class follow.
51    pub fn deserialize_changes_core(&self, reader: &mut BatchStreamReader<'_>, compositor: Option<&Rc<ServerCompositor>>) {
52        if reader.read::<u8>() == 1 {
53            let mut list = self.list.borrow_mut();
54            list.clear();
55            let count = reader.read::<i32>();
56            for _ in 0..count {
57                let Some(id) = reader.read_server_object() else {
58                    panic!("a batch lists a null item in a server list");
59                };
60                match compositor.and_then(|c| c.get_object(id)) {
61                    Some(object) => list.push(object),
62                    None => panic!("a batch refers to server object {id:?}, which does not exist"),
63                }
64            }
65        }
66    }
67}