Skip to main content

ferroui_controls_inking/
ink_synchronizer.rs

1use super::{InkError, InkPresenter, InkStroke};
2use std::cell::RefCell;
3use std::rc::{Rc, Weak};
4
5/// Transactional handoff from presenter-owned wet ink to application-owned dry ink.
6pub struct InkSynchronizer {
7    presenter: Weak<InkPresenter>,
8    active_batch: RefCell<Option<Vec<u32>>>,
9}
10impl PartialEq for InkSynchronizer {
11    fn eq(&self, other: &Self) -> bool {
12        std::ptr::eq(self, other)
13    }
14}
15
16impl InkSynchronizer {
17    pub(crate) fn new(presenter: Weak<InkPresenter>) -> Self {
18        Self {
19            presenter,
20            active_batch: RefCell::new(None),
21        }
22    }
23    pub fn begin_dry(&self) -> Result<Vec<Rc<InkStroke>>, InkError> {
24        if self.active_batch.borrow().is_some() {
25            return Err(InkError::InvalidOperation(
26                "a drying transaction is already active",
27            ));
28        }
29        let presenter = self
30            .presenter
31            .upgrade()
32            .ok_or(InkError::InvalidOperation("presenter was released"))?;
33        let strokes = presenter.pending_dry_strokes();
34        *self.active_batch.borrow_mut() = Some(strokes.iter().map(|s| s.id()).collect());
35        Ok(strokes)
36    }
37    pub fn end_dry(&self) -> Result<(), InkError> {
38        let ids = self
39            .active_batch
40            .borrow_mut()
41            .take()
42            .ok_or(InkError::InvalidOperation("begin_dry must precede end_dry"))?;
43        let presenter = self
44            .presenter
45            .upgrade()
46            .ok_or(InkError::InvalidOperation("presenter was released"))?;
47        presenter.finish_drying(&ids);
48        Ok(())
49    }
50}