1 use { 2 super::{ 3 Screen, 4 WIDE_STATUS, 5 }, 6 crate::{ 7 app::Panel, 8 errors::ProgramError, 9 }, 10 termimad::Area, 11 }; 12 13 /// the areas of the various parts of a panel. It's 14 /// also where a state usually checks how many panels 15 /// there are, and their respective positions 16 #[derive(Debug, Clone)] 17 pub struct Areas { 18 pub state: Area, 19 pub status: Area, 20 pub input: Area, 21 pub purpose: Option<Area>, 22 pub pos_idx: usize, // from left to right 23 pub nb_pos: usize, // number of displayed panels 24 } 25 26 const MINIMAL_PANEL_HEIGHT: u16 = 10; 27 const MINIMAL_PANEL_WIDTH: u16 = 20; 28 29 enum Slot<'a> { 30 Panel(usize), 31 New(&'a mut Areas), 32 } 33 34 impl Areas { 35 36 /// compute an area for a new panel which will be inserted create( present_panels: &mut [Panel], mut insertion_idx: usize, screen: Screen, with_preview: bool, ) -> Result<Self, ProgramError>37 pub fn create( 38 present_panels: &mut [Panel], 39 mut insertion_idx: usize, 40 screen: Screen, 41 with_preview: bool, // slightly larger last panel 42 ) -> Result<Self, ProgramError> { 43 if insertion_idx > present_panels.len() { 44 insertion_idx = present_panels.len(); 45 } 46 let mut areas = Areas { 47 state: Area::uninitialized(), 48 status: Area::uninitialized(), 49 input: Area::uninitialized(), 50 purpose: None, 51 pos_idx: 0, 52 nb_pos: 1, 53 }; 54 let mut slots = Vec::with_capacity(present_panels.len() + 1); 55 for i in 0..insertion_idx { 56 slots.push(Slot::Panel(i)); 57 } 58 slots.push(Slot::New(&mut areas)); 59 for i in insertion_idx..present_panels.len() { 60 slots.push(Slot::Panel(i)); 61 } 62 Self::compute_areas(present_panels, &mut slots, screen, with_preview)?; 63 Ok(areas) 64 } 65 resize_all( panels: &mut [Panel], screen: Screen, with_preview: bool, ) -> Result<(), ProgramError>66 pub fn resize_all( 67 panels: &mut [Panel], 68 screen: Screen, 69 with_preview: bool, // slightly larger last panel 70 ) -> Result<(), ProgramError> { 71 let mut slots = Vec::new(); 72 for i in 0..panels.len() { 73 slots.push(Slot::Panel(i)); 74 } 75 Self::compute_areas(panels, &mut slots, screen, with_preview) 76 } 77 compute_areas( panels: &mut [Panel], slots: &mut Vec<Slot>, screen: Screen, with_preview: bool, ) -> Result<(), ProgramError>78 fn compute_areas( 79 panels: &mut [Panel], 80 slots: &mut Vec<Slot>, 81 screen: Screen, 82 with_preview: bool, // slightly larger last panel 83 ) -> Result<(), ProgramError> { 84 if screen.height < MINIMAL_PANEL_HEIGHT { 85 return Err(ProgramError::TerminalTooSmallError); 86 } 87 let n = slots.len() as u16; 88 let mut panel_width = if with_preview { 89 3 * screen.width / (3 * n + 1) 90 } else { 91 screen.width / n 92 }; 93 if panel_width < MINIMAL_PANEL_WIDTH { 94 return Err(ProgramError::TerminalTooSmallError); 95 } 96 let mut x = 0; 97 let nb_pos = slots.len(); 98 #[allow(clippy::needless_range_loop)] 99 for slot_idx in 0..nb_pos { 100 if slot_idx == nb_pos - 1 { 101 panel_width = screen.width - x; 102 } 103 let areas: &mut Areas = match &mut slots[slot_idx] { 104 Slot::Panel(panel_idx) => &mut panels[*panel_idx].areas, 105 Slot::New(areas) => areas, 106 }; 107 let y = screen.height - 2; 108 areas.state = Area::new(x, 0, panel_width, y); 109 areas.status = if WIDE_STATUS { 110 Area::new(0, y, screen.width, 1) 111 } else { 112 Area::new(x, y, panel_width, 1) 113 }; 114 let y = y + 1; 115 areas.input = Area::new(x, y, panel_width, 1); 116 if slot_idx == nb_pos - 1 { 117 // the char at the bottom right of the terminal should not be touched 118 // (it makes some terminals flicker) so the input area is one char shorter 119 areas.input.width -= 1; 120 } 121 areas.purpose = if slot_idx > 0 { 122 let area_width = panel_width / 2; 123 Some(Area::new(x - area_width, y, area_width, 1)) 124 } else { 125 None 126 }; 127 areas.pos_idx = slot_idx; 128 areas.nb_pos = nb_pos; 129 x += panel_width; 130 } 131 Ok(()) 132 } 133 is_first(&self) -> bool134 pub fn is_first(&self) -> bool { 135 self.pos_idx == 0 136 } is_last(&self) -> bool137 pub fn is_last(&self) -> bool { 138 self.pos_idx + 1 == self.nb_pos 139 } 140 } 141