From 8dfa9902ef25a991f9ba947f7bacbbd962047c17 Mon Sep 17 00:00:00 2001 From: ac Date: Sat, 4 May 2024 11:57:45 +1000 Subject: [PATCH] Updated TabLayoutDescription to additionally store: window zoom & focus, and tab focus. --- crates/modalkit-ratatui/src/screen.rs | 17 +++++-- crates/modalkit-ratatui/src/windows/layout.rs | 45 +++++++++++++++++-- crates/modalkit-ratatui/src/windows/mod.rs | 7 ++- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/crates/modalkit-ratatui/src/screen.rs b/crates/modalkit-ratatui/src/screen.rs index 9019d44..3052f51 100644 --- a/crates/modalkit-ratatui/src/screen.rs +++ b/crates/modalkit-ratatui/src/screen.rs @@ -22,7 +22,7 @@ use ratatui::{ use super::{ cmdbar::{CommandBar, CommandBarState}, util::{rect_down, rect_zero_height}, - windows::{WindowActions, WindowLayout, WindowLayoutDescription, WindowLayoutState}, + windows::{WindowActions, WindowLayout, WindowLayoutState, WindowLayoutStorage}, TerminalCursor, Window, WindowOps, @@ -246,7 +246,9 @@ fn bold<'a>(s: String) -> Span<'a> { #[serde(bound(serialize = "I::WindowId: Serialize"))] pub struct TabLayoutDescription { /// The description of the window layout for each tab. - pub tabs: Vec>, + pub tabs: Vec>, + /// The index of the last focused tab + pub focused: usize, } impl TabLayoutDescription { @@ -256,11 +258,19 @@ impl TabLayoutDescription { area: Option, store: &mut Store, ) -> UIResult>, I> { + let focused = self.focused; self.tabs .into_iter() .map(|desc| desc.to_layout(area, store)) .collect::, I>>() - .map(FocusList::new) + .map(|layout| { + let mut focus = FocusList::new(layout); + let ctx = EditContext::default(); + // Count starts at 1 + let change = FocusChange::Offset(Count::Exact(focused + 1), true); + focus.focus(&change, &ctx); + focus + }) } } @@ -317,6 +327,7 @@ where pub fn as_description(&self) -> TabLayoutDescription { TabLayoutDescription { tabs: self.tabs.iter().map(WindowLayoutState::as_description).collect(), + focused: self.tabs.pos(), } } diff --git a/crates/modalkit-ratatui/src/windows/layout.rs b/crates/modalkit-ratatui/src/windows/layout.rs index f99653f..d19a223 100644 --- a/crates/modalkit-ratatui/src/windows/layout.rs +++ b/crates/modalkit-ratatui/src/windows/layout.rs @@ -1102,6 +1102,33 @@ where } } +/// Data structure holding layout description and state +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(bound(deserialize = "I::WindowId: Deserialize<'de>"))] +#[serde(bound(serialize = "I::WindowId: Serialize"))] +#[serde(rename_all = "lowercase", tag = "type")] +pub struct WindowLayoutStorage { + layout: WindowLayoutDescription, + focused: usize, + zoomed: bool, +} + +impl WindowLayoutStorage +where + I: ApplicationInfo, +{ + /// Restore a layout from a description of windows and splits. + pub fn to_layout>( + self, + area: Option, + store: &mut Store, + ) -> UIResult, I> { + let mut layout = self.layout.to_layout(area, store)?; + layout.focused = self.focused; + layout.zoom = self.zoomed; + Ok(layout) + } +} /// A description of a window layout. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(bound(deserialize = "I::WindowId: Deserialize<'de>"))] @@ -1282,18 +1309,28 @@ where } /// Convert this layout to a serializable summary of its windows and splits. - pub fn as_description(&self) -> WindowLayoutDescription { + pub fn as_description(&self) -> WindowLayoutStorage { let mut children = vec![]; + let focused = self.focused; + let zoomed = self.zoom; let Some(root) = &self.root else { - return WindowLayoutDescription::Split { children, length: None }; + return WindowLayoutStorage { + layout: WindowLayoutDescription::Split { children, length: None }, + focused, + zoomed, + }; }; for w in root.iter() { children.push(w.into()); } - return WindowLayoutDescription::Split { children, length: None }; + return WindowLayoutStorage { + layout: WindowLayoutDescription::Split { children, length: None }, + focused, + zoomed, + }; } /// Create a new instance containing a single [Window] displaying some content. @@ -2855,7 +2892,7 @@ mod tests { }], length: None, }; - assert_eq!(desc1, exp); + assert_eq!(desc1.layout, exp); // Turn back into a layout, and then generate a new description to show it's the same. let tree = desc1 diff --git a/crates/modalkit-ratatui/src/windows/mod.rs b/crates/modalkit-ratatui/src/windows/mod.rs index fbf2683..94e8221 100644 --- a/crates/modalkit-ratatui/src/windows/mod.rs +++ b/crates/modalkit-ratatui/src/windows/mod.rs @@ -30,7 +30,12 @@ mod size; mod slot; mod tree; -pub use self::layout::{WindowLayout, WindowLayoutDescription, WindowLayoutState}; +pub use self::layout::{ + WindowLayout, + WindowLayoutDescription, + WindowLayoutState, + WindowLayoutStorage, +}; struct AxisTreeNode { value: Value,