grid.rs 9.7 KB

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