145e17157SR0ronoa use std::{ 245e17157SR0ronoa any::Any, 345e17157SR0ronoa cell::{Cell, RefCell}, 445e17157SR0ronoa sync::Arc, 545e17157SR0ronoa }; 645e17157SR0ronoa 745e17157SR0ronoa use starry_client::base::renderer::Renderer; 8*b0262857SR0ronoa use starry_server::core::{SCREEN_HEIGHT, SCREEN_WIDTH}; 945e17157SR0ronoa 10*b0262857SR0ronoa use crate::base::{rect::Rect, vector2::Vector2}; 1145e17157SR0ronoa 1245e17157SR0ronoa pub mod image; 1345e17157SR0ronoa pub mod label; 1445e17157SR0ronoa 15*b0262857SR0ronoa pub fn widget_add_child(parent: Arc<dyn Widget>, child: Arc<dyn Widget>) { 16*b0262857SR0ronoa parent.children().borrow_mut().push(child.clone()); 17*b0262857SR0ronoa (*child.parent().borrow_mut()) = Some(parent.clone()); 18*b0262857SR0ronoa parent.arrange_all(); 1945e17157SR0ronoa } 2045e17157SR0ronoa 21*b0262857SR0ronoa /// # 函数功能 22*b0262857SR0ronoa /// 工具类 根据pivot和offset来进行矩形位置的对齐 23*b0262857SR0ronoa /// 24*b0262857SR0ronoa /// ## 参数 25*b0262857SR0ronoa /// - origin_rect: 待对齐的矩形 26*b0262857SR0ronoa /// - relative_rect: 作为对齐参考的矩形 27*b0262857SR0ronoa /// - pivot: 对齐方式 28*b0262857SR0ronoa /// - pivot_offset: 偏移量 29*b0262857SR0ronoa /// 30*b0262857SR0ronoa /// ## 返回值 31*b0262857SR0ronoa /// 对齐后的矩形 32*b0262857SR0ronoa pub fn align_rect( 33*b0262857SR0ronoa origin_rect: Rect, 34*b0262857SR0ronoa relative_rect: Rect, 35*b0262857SR0ronoa pivot: PivotType, 36*b0262857SR0ronoa pivot_offset: Vector2, 37*b0262857SR0ronoa ) -> Rect { 38*b0262857SR0ronoa let relative_pos = match pivot { 39*b0262857SR0ronoa PivotType::None => Vector2::new(0, 0), 40*b0262857SR0ronoa PivotType::Bottom => relative_rect.bottom_pos(), 41*b0262857SR0ronoa PivotType::BottomLeft => relative_rect.bottom_left_pos(), 42*b0262857SR0ronoa PivotType::BottomRight => relative_rect.bottom_right_pos(), 43*b0262857SR0ronoa PivotType::Center => relative_rect.center_pos(), 44*b0262857SR0ronoa PivotType::Top => relative_rect.top_pos(), 45*b0262857SR0ronoa PivotType::TopLeft => relative_rect.top_left_pos(), 46*b0262857SR0ronoa PivotType::TopRight => relative_rect.top_right_pos(), 47*b0262857SR0ronoa PivotType::Left => relative_rect.left_pos(), 48*b0262857SR0ronoa PivotType::Right => relative_rect.right_pos(), 49*b0262857SR0ronoa }; 50*b0262857SR0ronoa 51*b0262857SR0ronoa let mut target_pos = relative_pos + pivot_offset; 52*b0262857SR0ronoa 53*b0262857SR0ronoa let negative_width = -(origin_rect.width as i32); 54*b0262857SR0ronoa let negative_height = -(origin_rect.height as i32); 55*b0262857SR0ronoa let offset_vec = match pivot { 56*b0262857SR0ronoa PivotType::None => Vector2::new(0, 0), 57*b0262857SR0ronoa PivotType::Bottom => Vector2::new(negative_width / 2, negative_height), 58*b0262857SR0ronoa PivotType::BottomLeft => Vector2::new(0, negative_height), 59*b0262857SR0ronoa PivotType::BottomRight => Vector2::new(negative_width, negative_height), 60*b0262857SR0ronoa PivotType::Center => Vector2::new(negative_width / 2, negative_height / 2), 61*b0262857SR0ronoa PivotType::Top => Vector2::new(negative_width / 2, 0), 62*b0262857SR0ronoa PivotType::TopLeft => Vector2::new(0, 0), 63*b0262857SR0ronoa PivotType::TopRight => Vector2::new(negative_width, 0), 64*b0262857SR0ronoa PivotType::Left => Vector2::new(0, negative_height / 2), 65*b0262857SR0ronoa PivotType::Right => Vector2::new(negative_width, negative_height / 2), 66*b0262857SR0ronoa }; 67*b0262857SR0ronoa 68*b0262857SR0ronoa target_pos = target_pos + offset_vec; 69*b0262857SR0ronoa Rect::new( 70*b0262857SR0ronoa target_pos.x, 71*b0262857SR0ronoa target_pos.y, 72*b0262857SR0ronoa origin_rect.width, 73*b0262857SR0ronoa origin_rect.height, 74*b0262857SR0ronoa ) 75*b0262857SR0ronoa } 76*b0262857SR0ronoa 7745e17157SR0ronoa #[derive(PartialEq, Copy, Clone)] 78*b0262857SR0ronoa pub enum PivotType { 79*b0262857SR0ronoa /// 不进行对齐 pivot_offset即为世界坐标 80*b0262857SR0ronoa None, 81*b0262857SR0ronoa /// 对齐左上角(默认对齐方式,这是由于矩形位置通过左上角顶点坐标来表示) 82*b0262857SR0ronoa TopLeft, 83*b0262857SR0ronoa /// 对齐正上方 84*b0262857SR0ronoa Top, 85*b0262857SR0ronoa /// 对齐右上角 86*b0262857SR0ronoa TopRight, 87*b0262857SR0ronoa /// 对齐正左方 8845e17157SR0ronoa Left, 89*b0262857SR0ronoa /// 对齐中心 9045e17157SR0ronoa Center, 91*b0262857SR0ronoa /// 对齐正右方 9245e17157SR0ronoa Right, 93*b0262857SR0ronoa /// 对齐左下角 94*b0262857SR0ronoa BottomLeft, 95*b0262857SR0ronoa /// 对齐正下方 96*b0262857SR0ronoa Bottom, 97*b0262857SR0ronoa /// 对齐右下角 98*b0262857SR0ronoa BottomRight, 9945e17157SR0ronoa } 10045e17157SR0ronoa 10145e17157SR0ronoa /// UI组件需要实现的特性 10245e17157SR0ronoa pub trait Widget: Any { 10345e17157SR0ronoa /// 返回渲染的矩形区域 10445e17157SR0ronoa fn rect(&self) -> &Cell<Rect>; 10545e17157SR0ronoa 106*b0262857SR0ronoa /// 对齐方式 107*b0262857SR0ronoa fn pivot(&self) -> &Cell<PivotType>; 10845e17157SR0ronoa 109*b0262857SR0ronoa /// 基于基准点的偏移量 110*b0262857SR0ronoa fn pivot_offset(&self) -> &Cell<Vector2>; 11145e17157SR0ronoa 11245e17157SR0ronoa /// 返回组件的名字 11345e17157SR0ronoa fn name(&self) -> &str; 11445e17157SR0ronoa 115*b0262857SR0ronoa /// 返回父物体 116*b0262857SR0ronoa fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>>; 117*b0262857SR0ronoa 11845e17157SR0ronoa /// 返回子组件数组 11945e17157SR0ronoa fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>>; 12045e17157SR0ronoa 12145e17157SR0ronoa /// 渲染组件 1226f3c1837SR0ronoa fn draw(&self, renderer: &mut dyn Renderer, focused: bool); 12345e17157SR0ronoa 12445e17157SR0ronoa /// 更新组件状态 12545e17157SR0ronoa fn update(&self) {} 12645e17157SR0ronoa 127*b0262857SR0ronoa fn set_pivot_type(&self, pivot_type: PivotType) { 128*b0262857SR0ronoa self.set_pivot_type_base(pivot_type); 129*b0262857SR0ronoa } 130*b0262857SR0ronoa 131*b0262857SR0ronoa /// 修改对齐方式的统一处理 方便覆写 132*b0262857SR0ronoa fn set_pivot_type_base(&self, pivot_type: PivotType) { 133*b0262857SR0ronoa self.pivot().set(pivot_type); 134*b0262857SR0ronoa self.arrange_all(); 135*b0262857SR0ronoa } 136*b0262857SR0ronoa 137*b0262857SR0ronoa fn set_pivot_offset(&self, pivot_offset: Vector2) { 138*b0262857SR0ronoa self.set_pivot_offset_base(pivot_offset); 139*b0262857SR0ronoa } 140*b0262857SR0ronoa 141*b0262857SR0ronoa /// 修改对齐偏移量的统一处理 方便覆写 142*b0262857SR0ronoa fn set_pivot_offset_base(&self, pivot_offset: Vector2) { 143*b0262857SR0ronoa self.pivot_offset().set(pivot_offset); 144*b0262857SR0ronoa self.arrange_all(); 145*b0262857SR0ronoa } 146*b0262857SR0ronoa 147*b0262857SR0ronoa fn resize(&self, width: u32, height: u32) { 148*b0262857SR0ronoa self.resize_base(width, height); 149*b0262857SR0ronoa } 150*b0262857SR0ronoa 151*b0262857SR0ronoa /// 修改大小时的统一处理 方便覆写 152*b0262857SR0ronoa fn resize_base(&self, width: u32, height: u32) { 153*b0262857SR0ronoa let mut rect = self.rect().get(); 154*b0262857SR0ronoa rect.width = width; 155*b0262857SR0ronoa rect.height = height; 156*b0262857SR0ronoa self.rect().set(rect); 157*b0262857SR0ronoa self.arrange_all(); 158*b0262857SR0ronoa } 159*b0262857SR0ronoa 160*b0262857SR0ronoa /// 重新排布自身和子对象的位置 161*b0262857SR0ronoa fn arrange_all(&self) { 162*b0262857SR0ronoa self.arrange_self(); 16349182ea7SR0ronoa 16449182ea7SR0ronoa for child in self.children().borrow_mut().iter() { 165*b0262857SR0ronoa child.arrange_all(); 16649182ea7SR0ronoa } 16749182ea7SR0ronoa } 16849182ea7SR0ronoa 169*b0262857SR0ronoa fn arrange_self(&self) { 170*b0262857SR0ronoa self.arrange_self_base(); 17149182ea7SR0ronoa } 17249182ea7SR0ronoa 173*b0262857SR0ronoa /// 根据父物体和pivot值来调整自身位置 统一处理 方便覆写 174*b0262857SR0ronoa fn arrange_self_base(&self) { 175*b0262857SR0ronoa let relative_rect: Rect = if self.parent().borrow().is_some() { 176*b0262857SR0ronoa self.parent().borrow().as_ref().unwrap().rect().get() 177*b0262857SR0ronoa } else { 178*b0262857SR0ronoa // 没有父物体 则以整个屏幕作为参考 179*b0262857SR0ronoa Rect::new(0, 0, SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32) 180*b0262857SR0ronoa }; 181*b0262857SR0ronoa 182*b0262857SR0ronoa let target_rect = align_rect( 183*b0262857SR0ronoa self.rect().get(), 184*b0262857SR0ronoa relative_rect, 185*b0262857SR0ronoa self.pivot().get(), 186*b0262857SR0ronoa self.pivot_offset().get(), 187*b0262857SR0ronoa ); 188*b0262857SR0ronoa 189*b0262857SR0ronoa self.rect().set(target_rect); 19049182ea7SR0ronoa } 19145e17157SR0ronoa } 192