| 1 | //! Responsive list/detail geometry for settings pickers. |
| 2 | //! |
| 3 | //! Wide terminals place the option list beside a detail pane. Narrow terminals |
| 4 | //! stack (or, when the focused option prefers it, keep the list alone). |
| 5 | |
| 6 | use ratatui::layout::Rect; |
| 7 | |
| 8 | use crate::tui::views::ListDetailLayout; |
| 9 | |
| 10 | use super::option::SettingOption; |
| 11 | |
| 12 | /// Resolved panes for one settings-picker frame. |
| 13 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 14 | pub struct SettingsPickerLayout { |
| 15 | pub list: Rect, |
| 16 | pub detail: Option<Rect>, |
| 17 | pub stacked: bool, |
| 18 | pub narrow: bool, |
| 19 | } |
| 20 | |
| 21 | impl SettingsPickerLayout { |
| 22 | /// Split `area` using the shared list/detail contract, then optionally |
| 23 | /// collapse the detail pane when the focused option prefers list-only |
| 24 | /// narrow fallback. |
| 25 | #[must_use] |
| 26 | pub fn resolve(area: Rect, min_detail_width: u16, focused: Option<&SettingOption>) -> Self { |
| 27 | if area.width == 0 || area.height == 0 { |
| 28 | return Self { |
| 29 | list: area, |
| 30 | detail: None, |
| 31 | stacked: true, |
| 32 | narrow: true, |
| 33 | }; |
| 34 | } |
| 35 | |
| 36 | let base = ListDetailLayout::split(area, min_detail_width); |
| 37 | let narrow = base.stacked || area.width < 96; |
| 38 | let prefer_list = focused.is_some_and(|option| option.prefer_list_when_narrow); |
| 39 | |
| 40 | if narrow && prefer_list { |
| 41 | return Self { |
| 42 | list: area, |
| 43 | detail: None, |
| 44 | stacked: true, |
| 45 | narrow: true, |
| 46 | }; |
| 47 | } |
| 48 | |
| 49 | Self { |
| 50 | list: base.list, |
| 51 | detail: Some(base.detail), |
| 52 | stacked: base.stacked, |
| 53 | narrow, |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 |