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