ratatui_toolkit/widgets/markdown_widget/widget/methods/
sync_state_back.rs

1//! Sync widget state back to MarkdownState.
2
3use crate::widgets::markdown_widget::state::MarkdownState;
4use crate::widgets::markdown_widget::widget::MarkdownWidget;
5
6/// State captured from MarkdownWidget that needs to be synced back to MarkdownState.
7///
8/// This struct holds the values that the widget may modify during event handling
9/// that need to persist back to the application state.
10#[derive(Debug, Clone)]
11pub struct WidgetStateSync {
12    /// Whether the TOC is currently hovered.
13    pub toc_hovered: bool,
14    /// Index of the hovered TOC entry.
15    pub toc_hovered_entry: Option<usize>,
16    /// Scroll offset for the TOC list.
17    pub toc_scroll_offset: usize,
18    /// Whether selection mode is active.
19    pub selection_active: bool,
20    /// Last double-click info (line number, kind, content).
21    pub last_double_click: Option<(usize, String, String)>,
22    /// Current filter text (when in filter mode).
23    pub filter: Option<String>,
24    /// Whether filter mode is currently active.
25    pub filter_mode: bool,
26}
27
28impl WidgetStateSync {
29    /// Apply this sync state to a MarkdownState.
30    ///
31    /// # Arguments
32    ///
33    /// * `state` - The MarkdownState to sync state to
34    pub fn apply_to(&self, state: &mut MarkdownState) {
35        state.toc_hovered = self.toc_hovered;
36        state.toc_hovered_entry = self.toc_hovered_entry;
37        state.toc_scroll_offset = self.toc_scroll_offset;
38        state.selection_active = self.selection_active;
39        state.filter = self.filter.clone();
40        state.filter_mode = self.filter_mode;
41    }
42
43    /// Check if there was a double-click and consume it.
44    pub fn take_double_click(&mut self) -> Option<(usize, String, String)> {
45        self.last_double_click.take()
46    }
47}
48
49impl<'a> MarkdownWidget<'a> {
50    /// Get the state that needs to be synced back to MarkdownState.
51    ///
52    /// This method captures the TOC and selection state from the widget
53    /// so it can be synced back after the widget is dropped.
54    ///
55    /// # Returns
56    ///
57    /// A `WidgetStateSync` struct containing the state values to sync.
58    ///
59    /// # Example
60    ///
61    /// ```rust,ignore
62    /// let sync_state = {
63    ///     let mut widget = MarkdownWidget::from_state(&content, &mut state).show_toc(true);
64    ///     widget.handle_toc_hover(&mouse, render_area);
65    ///     widget.handle_toc_click(&mouse, render_area);
66    ///     widget.handle_mouse_event(&mouse, render_area);
67    ///     widget.get_state_sync()
68    /// };
69    /// sync_state.apply_to(&mut state);
70    /// ```
71    pub fn get_state_sync(&mut self) -> WidgetStateSync {
72        WidgetStateSync {
73            toc_hovered: self.toc_hovered,
74            toc_hovered_entry: self.toc_hovered_entry,
75            toc_scroll_offset: self.toc_scroll_offset,
76            selection_active: self.selection.is_active(),
77            last_double_click: self.last_double_click.take(),
78            filter: self.filter.clone(),
79            filter_mode: self.filter_mode,
80        }
81    }
82
83    /// Sync widget state back to MarkdownState by consuming self.
84    ///
85    /// This method consumes the widget and syncs TOC and selection state back to
86    /// the MarkdownState, ensuring state persistence between frames.
87    ///
88    /// Call this after handling mouse events to preserve hover and selection state.
89    ///
90    /// # Arguments
91    ///
92    /// * `state` - The MarkdownState to sync state back to
93    ///
94    /// # Example
95    ///
96    /// ```rust,ignore
97    /// let mut widget = MarkdownWidget::from_state(&content, &mut state).show_toc(true);
98    /// widget.handle_toc_hover(&mouse, render_area);
99    /// widget.handle_toc_click(&mouse, render_area);
100    /// widget.handle_mouse_event(&mouse, render_area);
101    /// widget.sync_state_back(&mut state);
102    /// ```
103    pub fn sync_state_back(self, state: &mut MarkdownState) {
104        state.toc_hovered = self.toc_hovered;
105        state.toc_hovered_entry = self.toc_hovered_entry;
106        state.toc_scroll_offset = self.toc_scroll_offset;
107        state.selection_active = self.selection.is_active();
108        state.filter = self.filter;
109        state.filter_mode = self.filter_mode;
110    }
111}