Skip to main content

mathtex_editor_core/
menu.rs

1//! Host facing state for the Backspace dropdown menu.
2
3use crate::host::Rect;
4use crate::model::NodeId;
5use crate::ops::SwapVariant;
6
7/// One row the host renders.
8#[derive(Debug, Clone, PartialEq)]
9pub struct MenuItem {
10    /// The visible row label.
11    pub label: String,
12}
13
14/// The data the host needs to draw and drive the open menu.
15#[derive(Debug, Clone, PartialEq)]
16pub struct MenuView {
17    /// The rectangle where the menu is anchored.
18    pub anchor: Rect,
19    /// The visible menu rows.
20    pub items: Vec<MenuItem>,
21    /// The selected row index.
22    pub selected: usize,
23    /// The typed filter query.
24    pub query: String,
25}
26
27/// A visible row effect.
28pub(crate) enum RowEffect<'a> {
29    Delete,
30    Swap(&'a SwapVariant),
31}
32
33impl RowEffect<'_> {
34    pub(crate) fn label(&self) -> String {
35        match self {
36            RowEffect::Delete => "Delete".to_string(),
37            RowEffect::Swap(v) => v.label().to_string(),
38        }
39    }
40}
41
42/// Editor private pending menu state.
43pub(crate) struct Menu {
44    pub(crate) anchor: NodeId,
45    variants: Vec<SwapVariant>,
46    pub(crate) query: String,
47    pub(crate) selected: usize,
48}
49
50impl Menu {
51    pub(crate) fn for_node(anchor: NodeId, variants: Vec<SwapVariant>) -> Self {
52        Self {
53            anchor,
54            variants,
55            query: String::new(),
56            selected: 0,
57        }
58    }
59
60    /// Rows currently shown to the host.
61    pub(crate) fn visible(&self) -> Vec<RowEffect<'_>> {
62        let mut out = vec![RowEffect::Delete];
63        let q = self.query.to_lowercase();
64        out.extend(
65            self.variants
66                .iter()
67                .filter(|v| q.is_empty() || v.label().to_lowercase().contains(&q))
68                .map(RowEffect::Swap),
69        );
70        out
71    }
72}