123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- use std::{
- cell::{Cell, RefCell},
- collections::BTreeMap,
- sync::Arc,
- };
- use starry_client::base::renderer::Renderer;
- use crate::{
- base::{event::Event, rect::Rect, vector2::Vector2},
- traits::{enter::Enter, focus::Focus},
- widgets::{PivotType, Widget},
- };
- /// 网格排列方式
- #[derive(PartialEq, Copy, Clone)]
- pub enum GridArrangeType {
- /// 优先横向排列
- Horizontal,
- /// 优先纵向排列
- Vertical,
- }
- pub struct Grid {
- pub rect: Cell<Rect>,
- pivot: Cell<PivotType>,
- pivot_offset: Cell<Vector2>,
- children: RefCell<Vec<Arc<dyn Widget>>>,
- parent: RefCell<Option<Arc<dyn Widget>>>,
- /// x坐标间隔
- space_x: Cell<i32>,
- /// y坐标间隔
- space_y: Cell<i32>,
- /// 每行/列的最大元素数
- upper_limit: Cell<usize>,
- /// 当前行数
- pub current_row: Cell<usize>,
- /// 当前列数
- pub current_column: Cell<usize>,
- /// 当前最大行数
- pub max_row: Cell<usize>,
- /// 当前最大列数
- pub max_column: Cell<usize>,
- /// 元素字典
- pub elements: RefCell<BTreeMap<(usize, usize), Arc<dyn Widget>>>,
- /// 当前选中的元素id(行列号)
- pub focused_id: Cell<Option<(usize, usize)>>,
- /// 当前聚焦的widget
- pub focused_widget: RefCell<Option<Arc<dyn Widget>>>,
- /// 优先排列方式
- arrange_type: Cell<GridArrangeType>,
- /// 键盘输入回调
- enter_callback: RefCell<Option<Arc<dyn Fn(&Self, char, &mut bool)>>>,
- }
- impl Grid {
- pub fn new() -> Arc<Self> {
- Arc::new(Grid {
- rect: Cell::new(Rect::default()),
- pivot: Cell::new(PivotType::TopLeft),
- pivot_offset: Cell::new(Vector2::new(0, 0)),
- children: RefCell::new(vec![]),
- parent: RefCell::new(None),
- space_x: Cell::new(0),
- space_y: Cell::new(0),
- upper_limit: Cell::new(0),
- current_row: Cell::new(0),
- current_column: Cell::new(0),
- max_row: Cell::new(0),
- max_column: Cell::new(0),
- elements: RefCell::new(BTreeMap::new()),
- focused_id: Cell::new(None),
- focused_widget: RefCell::new(None),
- arrange_type: Cell::new(GridArrangeType::Vertical),
- enter_callback: RefCell::new(None),
- })
- }
- /// 设置每行/列最大元素数量(取决于行/列优先排列)
- pub fn set_upper_limit(&self, columns: usize) -> &Self {
- self.upper_limit.set(columns);
- self
- }
- pub fn set_arrange_type(&self, arrange_type: GridArrangeType) -> &Self {
- self.arrange_type.set(arrange_type);
- self
- }
- pub fn add<T: Widget>(&self, element: &Arc<T>) -> (usize, usize) {
- self.find_next_slot();
- self.elements.borrow_mut().insert(
- (self.current_row.get(), self.current_column.get()),
- element.clone(),
- );
- let res = (self.current_row.get(), self.current_column.get());
- self.move_index();
- self.arrange_elements(false);
- return res;
- }
- /// 找到下一个可放置元素的位置
- fn find_next_slot(&self) {
- let elements = self.elements.borrow();
- while elements.contains_key(&(self.current_row.get(), self.current_column.get())) {
- self.move_index();
- }
- }
- fn move_index(&self) {
- match self.arrange_type.get() {
- GridArrangeType::Horizontal => {
- self.current_column.set(self.current_column.get() + 1);
- if self.current_column.get() == self.upper_limit.get() {
- self.current_row.set(self.current_row.get() + 1);
- self.current_column.set(0);
- }
- }
- GridArrangeType::Vertical => {
- self.current_row.set(self.current_row.get() + 1);
- if self.current_row.get() == self.upper_limit.get() {
- self.current_column.set(self.current_column.get() + 1);
- self.current_row.set(0);
- }
- }
- }
- }
- pub fn insert<T: Widget>(&self, column: usize, row: usize, element: &Arc<T>) {
- self.elements
- .borrow_mut()
- .insert((row, column), element.clone());
- self.arrange_elements(false);
- }
- pub fn remove(&self, column: usize, row: usize) {
- self.elements.borrow_mut().remove(&(row, column));
- }
- pub fn set_space(&self, x: i32, y: i32) -> &Self {
- self.space_x.set(x);
- self.space_y.set(y);
- self
- }
- // TODO 注释补充
- pub fn arrange_elements(&self, resize_children: bool) {
- if self.elements.borrow().is_empty() {
- return;
- }
- self.arrange_self();
- let mut cols = Vec::new();
- let mut rows = Vec::new();
- for (&(row, col), entry) in self.elements.borrow().iter() {
- while col >= cols.len() {
- cols.push(Rect::default());
- }
- while row >= rows.len() {
- rows.push(Rect::default());
- }
- let rect = entry.rect().get();
- if rect.width >= cols[col].width {
- cols[col as usize].width = rect.width;
- }
- if rect.width >= rows[row].width {
- rows[row as usize].width = rect.width;
- }
- if rect.height >= cols[col].height {
- cols[col as usize].height = rect.height;
- }
- if rect.height >= rows[row].height {
- rows[row as usize].height = rect.height;
- }
- }
- self.max_row.set(rows.len());
- self.max_column.set(cols.len());
- let space_x = self.space_x.get();
- let space_y = self.space_y.get();
- let mut x = 0;
- for col in cols.iter_mut() {
- col.x = x;
- x += col.width as i32 + space_x;
- }
- let mut y = 0;
- for row in rows.iter_mut() {
- row.y = y;
- y += row.height as i32 + space_y;
- }
- let grid_width = cols.len() as i32 * (cols[0].width as i32 + space_x) - space_x;
- let grid_height = rows.len() as i32 * (rows[0].width as i32 + space_y) - space_y;
- self.resize(grid_width as u32, grid_height as u32);
- for (&(row, col), child) in self.elements.borrow().iter() {
- child.set_pivot_type(PivotType::TopLeft);
- child.set_pivot_offset(Vector2::new(cols[col].x, rows[row].y));
- if resize_children {
- child.resize(cols[col].width, rows[row].height);
- }
- child.arrange_all();
- }
- }
- pub fn clear(&self) {
- self.children.borrow_mut().clear();
- self.elements.borrow_mut().clear();
- self.current_column.set(0);
- self.current_row.set(0);
- }
- }
- impl Widget for Grid {
- fn name(&self) -> &str {
- "Grid"
- }
- fn rect(&self) -> &Cell<Rect> {
- &self.rect
- }
- fn pivot(&self) -> &Cell<PivotType> {
- &self.pivot
- }
- fn pivot_offset(&self) -> &Cell<Vector2> {
- &self.pivot_offset
- }
- fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>> {
- &self.parent
- }
- fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> {
- &self.children
- }
- fn draw(&self, renderer: &mut dyn Renderer, _focused: bool) {
- for (&(_row, _col), widget) in self.elements.borrow().iter() {
- widget.update();
- widget.draw(renderer, self.is_focused(widget));
- }
- }
- fn handle_event(
- &self,
- event: Event,
- _focused: bool,
- redraw: &mut bool,
- caught: &mut bool,
- ) -> bool {
- match event {
- Event::KeyPressed { character, .. } => {
- if let Some(character) = character {
- self.emit_enter(character, redraw);
- }
- *caught = true;
- }
- // TODO
- _ => {}
- }
- false
- }
- }
- impl Focus for Grid {
- fn focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>> {
- self.focused_widget.clone()
- }
- fn focus(&self, widget: &Arc<dyn Widget>) {
- (*self.focused_widget.borrow_mut()) = Some(widget.clone());
- }
- }
- impl Enter for Grid {
- fn emit_enter(&self, char: char, redraw: &mut bool) {
- if let Some(ref enter_callback) = *self.enter_callback.borrow() {
- enter_callback(self, char, redraw);
- }
- }
- fn set_enter_callback<T: Fn(&Self, char, &mut bool) + 'static>(&self, func: T) {
- (*self.enter_callback.borrow_mut()) = Some(Arc::new(func));
- }
- }
|