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