1 use std::{ 2 cell::{Cell, RefCell}, 3 collections::BTreeMap, 4 sync::Arc, 5 }; 6 7 use starry_client::base::renderer::Renderer; 8 9 use crate::{ 10 base::{event::Event, rect::Rect, vector2::Vector2}, 11 traits::{enter::Enter, focus::Focus}, 12 widgets::{PivotType, Widget}, 13 }; 14 15 /// 网格排列方式 16 #[derive(PartialEq, Copy, Clone)] 17 pub enum GridArrangeType { 18 /// 优先横向排列 19 Horizontal, 20 /// 优先纵向排列 21 Vertical, 22 } 23 24 pub struct Grid { 25 pub rect: Cell<Rect>, 26 pivot: Cell<PivotType>, 27 pivot_offset: Cell<Vector2>, 28 children: RefCell<Vec<Arc<dyn Widget>>>, 29 parent: RefCell<Option<Arc<dyn Widget>>>, 30 /// x坐标间隔 31 space_x: Cell<i32>, 32 /// y坐标间隔 33 space_y: Cell<i32>, 34 /// 每行/列的最大元素数 35 upper_limit: Cell<usize>, 36 /// 当前行数 37 pub current_row: Cell<usize>, 38 /// 当前列数 39 pub current_column: Cell<usize>, 40 /// 当前最大行数 41 pub max_row: Cell<usize>, 42 /// 当前最大列数 43 pub max_column: Cell<usize>, 44 /// 元素字典 45 pub elements: RefCell<BTreeMap<(usize, usize), Arc<dyn Widget>>>, 46 /// 当前选中的元素id(行列号) 47 pub focused_id: Cell<Option<(usize, usize)>>, 48 /// 当前聚焦的widget 49 pub focused_widget: RefCell<Option<Arc<dyn Widget>>>, 50 /// 优先排列方式 51 arrange_type: Cell<GridArrangeType>, 52 /// 键盘输入回调 53 enter_callback: RefCell<Option<Arc<dyn Fn(&Self, char, &mut bool)>>>, 54 } 55 56 impl Grid { 57 pub fn new() -> Arc<Self> { 58 Arc::new(Grid { 59 rect: Cell::new(Rect::default()), 60 pivot: Cell::new(PivotType::TopLeft), 61 pivot_offset: Cell::new(Vector2::new(0, 0)), 62 children: RefCell::new(vec![]), 63 parent: RefCell::new(None), 64 space_x: Cell::new(0), 65 space_y: Cell::new(0), 66 upper_limit: Cell::new(0), 67 current_row: Cell::new(0), 68 current_column: Cell::new(0), 69 max_row: Cell::new(0), 70 max_column: Cell::new(0), 71 elements: RefCell::new(BTreeMap::new()), 72 focused_id: Cell::new(None), 73 focused_widget: RefCell::new(None), 74 arrange_type: Cell::new(GridArrangeType::Vertical), 75 enter_callback: RefCell::new(None), 76 }) 77 } 78 79 /// 设置每行/列最大元素数量(取决于行/列优先排列) 80 pub fn set_upper_limit(&self, columns: usize) -> &Self { 81 self.upper_limit.set(columns); 82 self 83 } 84 85 pub fn set_arrange_type(&self, arrange_type: GridArrangeType) -> &Self { 86 self.arrange_type.set(arrange_type); 87 self 88 } 89 90 pub fn add<T: Widget>(&self, element: &Arc<T>) -> (usize, usize) { 91 self.find_next_slot(); 92 self.elements.borrow_mut().insert( 93 (self.current_row.get(), self.current_column.get()), 94 element.clone(), 95 ); 96 let res = (self.current_row.get(), self.current_column.get()); 97 self.move_index(); 98 self.arrange_elements(false); 99 return res; 100 } 101 102 /// 找到下一个可放置元素的位置 103 fn find_next_slot(&self) { 104 let elements = self.elements.borrow(); 105 while elements.contains_key(&(self.current_row.get(), self.current_column.get())) { 106 self.move_index(); 107 } 108 } 109 110 fn move_index(&self) { 111 match self.arrange_type.get() { 112 GridArrangeType::Horizontal => { 113 self.current_column.set(self.current_column.get() + 1); 114 115 if self.current_column.get() == self.upper_limit.get() { 116 self.current_row.set(self.current_row.get() + 1); 117 self.current_column.set(0); 118 } 119 } 120 GridArrangeType::Vertical => { 121 self.current_row.set(self.current_row.get() + 1); 122 123 if self.current_row.get() == self.upper_limit.get() { 124 self.current_column.set(self.current_column.get() + 1); 125 self.current_row.set(0); 126 } 127 } 128 } 129 } 130 131 pub fn insert<T: Widget>(&self, column: usize, row: usize, element: &Arc<T>) { 132 self.elements 133 .borrow_mut() 134 .insert((row, column), element.clone()); 135 136 self.arrange_elements(false); 137 } 138 139 pub fn remove(&self, column: usize, row: usize) { 140 self.elements.borrow_mut().remove(&(row, column)); 141 } 142 143 pub fn set_space(&self, x: i32, y: i32) -> &Self { 144 self.space_x.set(x); 145 self.space_y.set(y); 146 self 147 } 148 149 // TODO 注释补充 150 pub fn arrange_elements(&self, resize_children: bool) { 151 if self.elements.borrow().is_empty() { 152 return; 153 } 154 155 self.arrange_self(); 156 157 let mut cols = Vec::new(); 158 let mut rows = Vec::new(); 159 for (&(row, col), entry) in self.elements.borrow().iter() { 160 while col >= cols.len() { 161 cols.push(Rect::default()); 162 } 163 while row >= rows.len() { 164 rows.push(Rect::default()); 165 } 166 let rect = entry.rect().get(); 167 if rect.width >= cols[col].width { 168 cols[col as usize].width = rect.width; 169 } 170 if rect.width >= rows[row].width { 171 rows[row as usize].width = rect.width; 172 } 173 if rect.height >= cols[col].height { 174 cols[col as usize].height = rect.height; 175 } 176 if rect.height >= rows[row].height { 177 rows[row as usize].height = rect.height; 178 } 179 } 180 181 self.max_row.set(rows.len()); 182 self.max_column.set(cols.len()); 183 184 let space_x = self.space_x.get(); 185 let space_y = self.space_y.get(); 186 187 let mut x = 0; 188 for col in cols.iter_mut() { 189 col.x = x; 190 x += col.width as i32 + space_x; 191 } 192 193 let mut y = 0; 194 for row in rows.iter_mut() { 195 row.y = y; 196 y += row.height as i32 + space_y; 197 } 198 199 let grid_width = cols.len() as i32 * (cols[0].width as i32 + space_x) - space_x; 200 let grid_height = rows.len() as i32 * (rows[0].width as i32 + space_y) - space_y; 201 self.resize(grid_width as u32, grid_height as u32); 202 203 for (&(row, col), child) in self.elements.borrow().iter() { 204 child.set_pivot_type(PivotType::TopLeft); 205 child.set_pivot_offset(Vector2::new(cols[col].x, rows[row].y)); 206 if resize_children { 207 child.resize(cols[col].width, rows[row].height); 208 } 209 210 child.arrange_all(); 211 } 212 } 213 214 pub fn clear(&self) { 215 self.children.borrow_mut().clear(); 216 self.elements.borrow_mut().clear(); 217 self.current_column.set(0); 218 self.current_row.set(0); 219 } 220 } 221 222 impl Widget for Grid { 223 fn name(&self) -> &str { 224 "Grid" 225 } 226 227 fn rect(&self) -> &Cell<Rect> { 228 &self.rect 229 } 230 231 fn pivot(&self) -> &Cell<PivotType> { 232 &self.pivot 233 } 234 235 fn pivot_offset(&self) -> &Cell<Vector2> { 236 &self.pivot_offset 237 } 238 239 fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>> { 240 &self.parent 241 } 242 243 fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> { 244 &self.children 245 } 246 247 fn draw(&self, renderer: &mut dyn Renderer, _focused: bool) { 248 for (&(_row, _col), widget) in self.elements.borrow().iter() { 249 widget.update(); 250 widget.draw(renderer, self.is_focused(widget)); 251 } 252 } 253 254 fn handle_event( 255 &self, 256 event: Event, 257 _focused: bool, 258 redraw: &mut bool, 259 caught: &mut bool, 260 ) -> bool { 261 match event { 262 Event::KeyPressed { character, .. } => { 263 if let Some(character) = character { 264 self.emit_enter(character, redraw); 265 } 266 267 *caught = true; 268 } 269 // TODO 270 _ => {} 271 } 272 false 273 } 274 } 275 276 impl Focus for Grid { 277 fn focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>> { 278 self.focused_widget.clone() 279 } 280 281 fn focus(&self, widget: &Arc<dyn Widget>) { 282 (*self.focused_widget.borrow_mut()) = Some(widget.clone()); 283 } 284 } 285 286 impl Enter for Grid { 287 fn emit_enter(&self, char: char, redraw: &mut bool) { 288 if let Some(ref enter_callback) = *self.enter_callback.borrow() { 289 enter_callback(self, char, redraw); 290 } 291 } 292 293 fn set_enter_callback<T: Fn(&Self, char, &mut bool) + 'static>(&self, func: T) { 294 (*self.enter_callback.borrow_mut()) = Some(Arc::new(func)); 295 } 296 } 297