xref: /StarryEngine/starry_toolkit/src/widgets/mod.rs (revision 731cae0674923fcc85c6e683a2eee596eb642796)
145e17157SR0ronoa use std::{
245e17157SR0ronoa     any::Any,
345e17157SR0ronoa     cell::{Cell, RefCell},
445e17157SR0ronoa     sync::Arc,
545e17157SR0ronoa };
645e17157SR0ronoa 
745e17157SR0ronoa use starry_client::base::renderer::Renderer;
8b0262857SR0ronoa use starry_server::core::{SCREEN_HEIGHT, SCREEN_WIDTH};
945e17157SR0ronoa 
101bee64b6SR0ronoa use crate::{
111bee64b6SR0ronoa     base::{event::Event, panel::Panel, rect::Rect, vector2::Vector2},
121bee64b6SR0ronoa     util::{align_rect, widget_set_panel},
131bee64b6SR0ronoa };
1445e17157SR0ronoa 
1545e17157SR0ronoa pub mod image;
1645e17157SR0ronoa pub mod label;
1745e17157SR0ronoa 
18*731cae06SR0ronoa /// 控件对齐类型
191bee64b6SR0ronoa #[derive(PartialEq, Copy, Clone, Debug)]
20b0262857SR0ronoa pub enum PivotType {
21b0262857SR0ronoa     /// 不进行对齐 pivot_offset即为世界坐标
22b0262857SR0ronoa     None,
23b0262857SR0ronoa     /// 对齐左上角(默认对齐方式,这是由于矩形位置通过左上角顶点坐标来表示)
24b0262857SR0ronoa     TopLeft,
25b0262857SR0ronoa     /// 对齐正上方
26b0262857SR0ronoa     Top,
27b0262857SR0ronoa     /// 对齐右上角
28b0262857SR0ronoa     TopRight,
29b0262857SR0ronoa     /// 对齐正左方
3045e17157SR0ronoa     Left,
31b0262857SR0ronoa     /// 对齐中心
3245e17157SR0ronoa     Center,
33b0262857SR0ronoa     /// 对齐正右方
3445e17157SR0ronoa     Right,
35b0262857SR0ronoa     /// 对齐左下角
36b0262857SR0ronoa     BottomLeft,
37b0262857SR0ronoa     /// 对齐正下方
38b0262857SR0ronoa     Bottom,
39b0262857SR0ronoa     /// 对齐右下角
40b0262857SR0ronoa     BottomRight,
4145e17157SR0ronoa }
4245e17157SR0ronoa 
4345e17157SR0ronoa ///  UI组件需要实现的特性
4445e17157SR0ronoa pub trait Widget: Any {
452b942a51SR0ronoa     /// 返回自身指针
self_ref(&self) -> Arc<dyn Widget>462b942a51SR0ronoa     fn self_ref(&self) -> Arc<dyn Widget>;
472b942a51SR0ronoa 
481bee64b6SR0ronoa     /// 返回Any引用
as_any_ref(&self) -> &dyn Any491bee64b6SR0ronoa     fn as_any_ref(&self) -> &dyn Any;
501bee64b6SR0ronoa 
5145e17157SR0ronoa     /// 返回渲染的矩形区域
rect(&self) -> &Cell<Rect>5245e17157SR0ronoa     fn rect(&self) -> &Cell<Rect>;
5345e17157SR0ronoa 
54b0262857SR0ronoa     /// 对齐方式
pivot(&self) -> &Cell<PivotType>55b0262857SR0ronoa     fn pivot(&self) -> &Cell<PivotType>;
5645e17157SR0ronoa 
57b0262857SR0ronoa     /// 基于基准点的偏移量
pivot_offset(&self) -> &Cell<Vector2>58b0262857SR0ronoa     fn pivot_offset(&self) -> &Cell<Vector2>;
5945e17157SR0ronoa 
601bee64b6SR0ronoa     /// 所属面板
panel(&self) -> &RefCell<Option<Arc<Panel>>>611bee64b6SR0ronoa     fn panel(&self) -> &RefCell<Option<Arc<Panel>>>;
622b942a51SR0ronoa 
6345e17157SR0ronoa     /// 返回组件的名字
name(&self) -> &str6445e17157SR0ronoa     fn name(&self) -> &str;
6545e17157SR0ronoa 
6645e17157SR0ronoa     /// 返回子组件数组
children(&self) -> &RefCell<Vec<Arc<dyn Widget>>>6745e17157SR0ronoa     fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>>;
6845e17157SR0ronoa 
692b942a51SR0ronoa     /// 父物体
parent(&self) -> &RefCell<Option<Arc<dyn Widget>>>702b942a51SR0ronoa     fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>>;
712b942a51SR0ronoa 
722b942a51SR0ronoa     /// 添加子物体
add_child(&self, widget: Arc<dyn Widget>)732b942a51SR0ronoa     fn add_child(&self, widget: Arc<dyn Widget>) {
742b942a51SR0ronoa         self.children().borrow_mut().push(widget.clone());
751bee64b6SR0ronoa 
761bee64b6SR0ronoa         // 赋值父物体
772b942a51SR0ronoa         (*widget.parent().borrow_mut()) = Some(self.self_ref());
781bee64b6SR0ronoa 
791bee64b6SR0ronoa         // 赋值所属的面板
801bee64b6SR0ronoa         if self.panel().borrow().is_some() {
811bee64b6SR0ronoa             widget_set_panel(&widget, &self.panel().borrow().clone().unwrap());
821bee64b6SR0ronoa         }
832b942a51SR0ronoa     }
842b942a51SR0ronoa 
8545e17157SR0ronoa     /// 渲染组件
draw(&self, renderer: &mut dyn Renderer, focused: bool)866f3c1837SR0ronoa     fn draw(&self, renderer: &mut dyn Renderer, focused: bool);
8745e17157SR0ronoa 
8845e17157SR0ronoa     /// 更新组件状态
update(&self)8945e17157SR0ronoa     fn update(&self) {}
9045e17157SR0ronoa 
918a41b76cSR0ronoa     /// 处理输入事件
handle_event( &self, _event: Event, _focused: bool, _redraw: &Cell<bool>, _caught: &Cell<bool>, ) -> bool928a41b76cSR0ronoa     fn handle_event(
938a41b76cSR0ronoa         &self,
948a41b76cSR0ronoa         _event: Event,
958a41b76cSR0ronoa         _focused: bool,
961bee64b6SR0ronoa         _redraw: &Cell<bool>,
971bee64b6SR0ronoa         _caught: &Cell<bool>,
988a41b76cSR0ronoa     ) -> bool {
998a41b76cSR0ronoa         false
1008a41b76cSR0ronoa     }
1018a41b76cSR0ronoa 
set_pivot_type(&self, pivot_type: PivotType)102b0262857SR0ronoa     fn set_pivot_type(&self, pivot_type: PivotType) {
103b0262857SR0ronoa         self.set_pivot_type_base(pivot_type);
104b0262857SR0ronoa     }
105b0262857SR0ronoa 
106b0262857SR0ronoa     /// 修改对齐方式的统一处理 方便覆写
set_pivot_type_base(&self, pivot_type: PivotType)107b0262857SR0ronoa     fn set_pivot_type_base(&self, pivot_type: PivotType) {
108b0262857SR0ronoa         self.pivot().set(pivot_type);
109b0262857SR0ronoa         self.arrange_all();
110b0262857SR0ronoa     }
111b0262857SR0ronoa 
set_pivot_offset(&self, pivot_offset: Vector2)112b0262857SR0ronoa     fn set_pivot_offset(&self, pivot_offset: Vector2) {
113b0262857SR0ronoa         self.set_pivot_offset_base(pivot_offset);
114b0262857SR0ronoa     }
115b0262857SR0ronoa 
116b0262857SR0ronoa     /// 修改对齐偏移量的统一处理 方便覆写
set_pivot_offset_base(&self, pivot_offset: Vector2)117b0262857SR0ronoa     fn set_pivot_offset_base(&self, pivot_offset: Vector2) {
118b0262857SR0ronoa         self.pivot_offset().set(pivot_offset);
119b0262857SR0ronoa         self.arrange_all();
120b0262857SR0ronoa     }
121b0262857SR0ronoa 
resize(&self, width: u32, height: u32)122b0262857SR0ronoa     fn resize(&self, width: u32, height: u32) {
123b0262857SR0ronoa         self.resize_base(width, height);
124b0262857SR0ronoa     }
125b0262857SR0ronoa 
126b0262857SR0ronoa     /// 修改大小时的统一处理 方便覆写
resize_base(&self, width: u32, height: u32)127b0262857SR0ronoa     fn resize_base(&self, width: u32, height: u32) {
128b0262857SR0ronoa         let mut rect = self.rect().get();
129b0262857SR0ronoa         rect.width = width;
130b0262857SR0ronoa         rect.height = height;
131b0262857SR0ronoa         self.rect().set(rect);
132b0262857SR0ronoa         self.arrange_all();
133b0262857SR0ronoa     }
134b0262857SR0ronoa 
135b0262857SR0ronoa     /// 重新排布自身和子对象的位置
arrange_all(&self)136b0262857SR0ronoa     fn arrange_all(&self) {
137b0262857SR0ronoa         self.arrange_self();
13849182ea7SR0ronoa 
13949182ea7SR0ronoa         for child in self.children().borrow_mut().iter() {
140b0262857SR0ronoa             child.arrange_all();
14149182ea7SR0ronoa         }
14249182ea7SR0ronoa     }
14349182ea7SR0ronoa 
arrange_self(&self)144b0262857SR0ronoa     fn arrange_self(&self) {
145b0262857SR0ronoa         self.arrange_self_base();
14649182ea7SR0ronoa     }
14749182ea7SR0ronoa 
1482b942a51SR0ronoa     /// 根据参考的矩形和pivot值来调整自身位置(默认为父物体,也可以自定义为其他矩形)
1492b942a51SR0ronoa     /// 统一处理 方便覆写
arrange_self_base(&self)150b0262857SR0ronoa     fn arrange_self_base(&self) {
151b0262857SR0ronoa         let relative_rect: Rect = if self.parent().borrow().is_some() {
1522b942a51SR0ronoa             // 优先以父物体作为参考
1532b942a51SR0ronoa             self.parent().borrow().clone().unwrap().rect().get()
1541bee64b6SR0ronoa         } else if self.panel().borrow().is_some() {
1552b942a51SR0ronoa             // 没有父物体 则以所属面板作为参考
1561bee64b6SR0ronoa             self.panel().borrow().clone().unwrap().rect()
157b0262857SR0ronoa         } else {
1582b942a51SR0ronoa             // 否则以整个屏幕作为参考
159b0262857SR0ronoa             Rect::new(0, 0, SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32)
160b0262857SR0ronoa         };
161b0262857SR0ronoa 
162b0262857SR0ronoa         let target_rect = align_rect(
163b0262857SR0ronoa             self.rect().get(),
164b0262857SR0ronoa             relative_rect,
165b0262857SR0ronoa             self.pivot().get(),
166b0262857SR0ronoa             self.pivot_offset().get(),
167b0262857SR0ronoa         );
168b0262857SR0ronoa 
169b0262857SR0ronoa         self.rect().set(target_rect);
17049182ea7SR0ronoa     }
17145e17157SR0ronoa }
172