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::{panel::Panel, rect::Rect, vector2::Vector2}, 12 traits::focus::Focus, 13 widgets::{PivotType, Widget}, 14 }; 15 16 #[derive(PartialEq, Copy, Clone)] 17 pub enum ListArrangeType { 18 /// 横向排列 19 Horizontal, 20 /// 纵向排列 21 Vertical, 22 } 23 24 #[derive(PartialEq, Copy, Clone)] 25 pub enum ListElementPivotType { 26 LeftOrTop, 27 Center, 28 RightOrBottom, 29 } 30 31 pub struct List { 32 self_ref: RefCell<Weak<List>>, 33 rect: Cell<Rect>, 34 pivot: Cell<PivotType>, 35 pivot_offset: Cell<Vector2>, 36 children: RefCell<Vec<Arc<dyn Widget>>>, 37 parent: RefCell<Option<Arc<dyn Widget>>>, 38 panel: RefCell<Option<Arc<Panel>>>, 39 40 space: Cell<u32>, 41 current_index: Cell<usize>, 42 elements: RefCell<BTreeMap<usize, Arc<dyn Widget>>>, 43 focused_id: Cell<Option<usize>>, 44 focused_widget: RefCell<Option<Arc<dyn Widget>>>, 45 46 arrange_type: Cell<ListArrangeType>, 47 element_pivot_type: Cell<ListElementPivotType>, 48 } 49 50 impl List { new() -> Arc<Self>51 pub fn new() -> Arc<Self> { 52 let list = Arc::new(List { 53 self_ref: RefCell::new(Weak::default()), 54 rect: Cell::new(Rect::default()), 55 pivot: Cell::new(PivotType::TopLeft), 56 pivot_offset: Cell::new(Vector2::new(0, 0)), 57 children: RefCell::new(vec![]), 58 parent: RefCell::new(None), 59 panel: RefCell::new(None), 60 space: Cell::new(0), 61 current_index: Cell::new(0), 62 elements: RefCell::new(BTreeMap::new()), 63 focused_id: Cell::new(None), 64 focused_widget: RefCell::new(None), 65 arrange_type: Cell::new(ListArrangeType::Vertical), 66 element_pivot_type: Cell::new(ListElementPivotType::Center), 67 }); 68 69 (*list.self_ref.borrow_mut()) = Arc::downgrade(&list); 70 71 return list; 72 } 73 set_arrange_type(&self, arrange_type: ListArrangeType) -> &Self74 pub fn set_arrange_type(&self, arrange_type: ListArrangeType) -> &Self { 75 self.arrange_type.set(arrange_type); 76 self 77 } 78 set_space(&self, space: u32) -> &Self79 pub fn set_space(&self, space: u32) -> &Self { 80 self.space.set(space); 81 self 82 } 83 add_element<T: Widget>(&self, element: &Arc<T>) -> usize84 pub fn add_element<T: Widget>(&self, element: &Arc<T>) -> usize { 85 self.add_child(element.self_ref()); 86 87 self.elements 88 .borrow_mut() 89 .insert(self.current_index.get(), element.clone()); 90 91 let res = self.current_index.get(); 92 self.current_index.set(res + 1); 93 self.arrange_elements(); 94 return res; 95 } 96 arrange_elements(&self)97 pub fn arrange_elements(&self) { 98 if self.elements.borrow().is_empty() { 99 return; 100 } 101 102 self.arrange_self(); 103 104 // 遍历找到最大的长或宽值 105 let mut max_size: u32 = 0; 106 for (&_index, element) in self.elements.borrow().iter() { 107 match self.arrange_type.get() { 108 ListArrangeType::Horizontal => { 109 max_size = u32::max(max_size, element.rect().get().height); 110 } 111 ListArrangeType::Vertical => { 112 max_size = u32::max(max_size, element.rect().get().width); 113 } 114 } 115 } 116 117 let mut x_offset: u32 = 0; 118 let mut y_offset: u32 = 0; 119 120 for (&_index, element) in self.elements.borrow().iter() { 121 let align_vector: Vector2; 122 match self.arrange_type.get() { 123 ListArrangeType::Horizontal => { 124 align_vector = match self.element_pivot_type.get() { 125 ListElementPivotType::LeftOrTop => { 126 Vector2::new(x_offset as i32, y_offset as i32) 127 } 128 ListElementPivotType::Center => Vector2::new( 129 x_offset as i32, 130 y_offset as i32 + (max_size - element.rect().get().height) as i32 / 2, 131 ), 132 ListElementPivotType::RightOrBottom => Vector2::new( 133 x_offset as i32, 134 y_offset as i32 + (max_size - element.rect().get().height) as i32, 135 ), 136 }; 137 } 138 ListArrangeType::Vertical => { 139 align_vector = match self.element_pivot_type.get() { 140 ListElementPivotType::LeftOrTop => { 141 Vector2::new(x_offset as i32, y_offset as i32) 142 } 143 ListElementPivotType::Center => Vector2::new( 144 x_offset as i32 + (max_size - element.rect().get().width) as i32 / 2, 145 y_offset as i32, 146 ), 147 ListElementPivotType::RightOrBottom => Vector2::new( 148 x_offset as i32 + (max_size - element.rect().get().width) as i32, 149 y_offset as i32, 150 ), 151 } 152 } 153 } 154 155 element.set_pivot_type(PivotType::TopLeft); 156 element.set_pivot_offset(align_vector); 157 element.arrange_all(); 158 159 match self.arrange_type.get() { 160 ListArrangeType::Horizontal => { 161 x_offset += element.rect().get().width + self.space.get(); 162 } 163 ListArrangeType::Vertical => { 164 y_offset += element.rect().get().height + self.space.get(); 165 } 166 } 167 } 168 } 169 } 170 171 impl Widget for List { self_ref(&self) -> Arc<dyn Widget>172 fn self_ref(&self) -> Arc<dyn Widget> { 173 self.self_ref.borrow().upgrade().unwrap() 174 } 175 as_any_ref(&self) -> &dyn Any176 fn as_any_ref(&self) -> &dyn Any { 177 self 178 } 179 name(&self) -> &str180 fn name(&self) -> &str { 181 "List" 182 } 183 rect(&self) -> &Cell<Rect>184 fn rect(&self) -> &Cell<Rect> { 185 &self.rect 186 } 187 pivot(&self) -> &Cell<PivotType>188 fn pivot(&self) -> &Cell<PivotType> { 189 &self.pivot 190 } 191 pivot_offset(&self) -> &Cell<Vector2>192 fn pivot_offset(&self) -> &Cell<Vector2> { 193 &self.pivot_offset 194 } 195 parent(&self) -> &RefCell<Option<Arc<dyn Widget>>>196 fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>> { 197 &self.parent 198 } 199 children(&self) -> &RefCell<Vec<Arc<dyn Widget>>>200 fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> { 201 &self.children 202 } 203 panel(&self) -> &RefCell<Option<Arc<Panel>>>204 fn panel(&self) -> &RefCell<Option<Arc<Panel>>> { 205 &self.panel 206 } 207 draw(&self, renderer: &mut dyn Renderer, _focused: bool)208 fn draw(&self, renderer: &mut dyn Renderer, _focused: bool) { 209 for (&_index, widget) in self.elements.borrow().iter() { 210 widget.update(); 211 widget.draw(renderer, self.is_focused(widget)); 212 } 213 } 214 handle_event( &self, _event: crate::base::event::Event, _focused: bool, _redraw: &Cell<bool>, _caught: &Cell<bool>, ) -> bool215 fn handle_event( 216 &self, 217 _event: crate::base::event::Event, 218 _focused: bool, 219 _redraw: &Cell<bool>, 220 _caught: &Cell<bool>, 221 ) -> bool { 222 false 223 } 224 } 225 226 impl Focus for List { focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>>227 fn focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>> { 228 self.focused_widget.clone() 229 } 230 focus(&self, focused_widget: &Arc<dyn Widget>)231 fn focus(&self, focused_widget: &Arc<dyn Widget>) { 232 // 同时更新focused_id 233 for (&index, widget) in self.elements.borrow().iter() { 234 if Arc::ptr_eq(widget, focused_widget) { 235 self.focused_id.set(Some(index)); 236 (*self.focused_widget.borrow_mut()) = Some(focused_widget.clone()); 237 } 238 } 239 } 240 } 241