xref: /StarryEngine/starry_toolkit/src/base/panel.rs (revision f33c7b22a5870071cca9eef34949e88cd35c55ba)
1 use std::{
2     cell::{Cell, RefCell},
3     sync::Arc,
4 };
5 
6 use starry_client::{
7     base::{
8         color::Color,
9         renderer::{RenderMode, Renderer},
10     },
11     window::Window,
12 };
13 
14 use crate::widgets::Widget;
15 
16 use super::rect::Rect;
17 
18 /// 面板渲染器
19 pub struct PanelRenderer<'a> {
20     /// 客户端窗口
21     window: &'a mut Window,
22 }
23 
24 impl<'a> PanelRenderer<'a> {
25     pub fn new(window: &'a mut Window) -> Self {
26         PanelRenderer { window }
27     }
28 }
29 
30 impl<'a> Renderer for PanelRenderer<'a> {
31     fn width(&self) -> u32 {
32         self.window.width()
33     }
34 
35     fn height(&self) -> u32 {
36         self.window.height()
37     }
38 
39     fn data(&self) -> &[Color] {
40         self.window.data()
41     }
42 
43     fn data_mut(&mut self) -> &mut [Color] {
44         self.window.data_mut()
45     }
46 
47     fn sync(&mut self) -> bool {
48         self.window.sync()
49     }
50 
51     fn mode(&self) -> &Cell<RenderMode> {
52         &self.window.mode()
53     }
54 
55     // TODO
56     // fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
57     // }
58 }
59 
60 impl<'a> Drop for PanelRenderer<'a> {
61     fn drop(&mut self) {
62         self.window.sync();
63     }
64 }
65 
66 /// UI面板类作为容器管理一组UI组件(UI-Widget)
67 /// 拥有一个窗口对象用于渲染和事件传递
68 pub struct Panel {
69     /// 客户端窗口对象
70     window: RefCell<Window>,
71     /// 子组件数组
72     pub widgets: RefCell<Vec<Arc<dyn Widget>>>,
73     /// 窗口是否打开
74     pub running: Cell<bool>,
75 }
76 
77 impl Panel {
78     pub fn new(rect: Rect, title: &str) -> Self {
79         Panel::from_window(Window::new(rect.x, rect.y, rect.width, rect.height, title))
80     }
81 
82     pub fn from_window(window: Window) -> Self {
83         Panel {
84             window: RefCell::new(window),
85             widgets: RefCell::new(Vec::new()),
86             running: Cell::new(true),
87         }
88     }
89 
90     /// 获得客户端窗口对象
91     pub fn into_window(self) -> Window {
92         self.window.into_inner()
93     }
94 
95     /// 返回x坐标
96     pub fn x(&self) -> i32 {
97         let window = self.window.borrow();
98         (*window).x()
99     }
100 
101     /// 返回y坐标
102     pub fn y(&self) -> i32 {
103         let window = self.window.borrow();
104         (*window).y()
105     }
106 
107     /// 返回宽度值
108     pub fn width(&self) -> u32 {
109         let window = self.window.borrow();
110         (*window).width()
111     }
112 
113     /// 返回高度值
114     pub fn height(&self) -> u32 {
115         let window = self.window.borrow();
116         (*window).height()
117     }
118 
119     /// 窗口标题
120     pub fn title(&self) -> String {
121         let window = self.window.borrow();
122         (*window).title()
123     }
124 
125     /// 改变窗口位置
126     pub fn set_pos(&self, x: i32, y: i32) {
127         let mut window = self.window.borrow_mut();
128         (*window).set_pos(x, y);
129     }
130 
131     /// 改变窗口大小
132     pub fn set_size(&self, width: u32, height: u32) {
133         let mut window = self.window.borrow_mut();
134         (*window).set_size(width, height);
135     }
136 
137     /// 改变窗口标题
138     pub fn set_title(&self, title: &str) {
139         let mut window = self.window.borrow_mut();
140         (*window).set_title(title);
141     }
142 
143     /// 关闭窗口
144     pub fn close(&self) {
145         self.running.set(false);
146     }
147 
148     /// 添加子组件,返回子组件id
149     pub fn add_child<T: Widget>(&self, widget: &Arc<T>) -> usize {
150         let mut widgets = self.widgets.borrow_mut();
151         let id = widgets.len();
152         widgets.push(widget.clone());
153 
154         return id;
155     }
156 
157     /// 渲染面板(渲染子组件数组)
158     pub fn draw(&self) {
159         let mut window = self.window.borrow_mut();
160         let mut renderer = PanelRenderer::new(&mut window);
161 
162         for widget in self.widgets.borrow().iter() {
163             self.draw_widget(&mut renderer, widget);
164         }
165 
166         renderer.sync();
167     }
168 
169     /// 渲染单个组件
170     pub fn draw_widget(&self, renderer: &mut dyn Renderer, widget: &Arc<dyn Widget>) {
171         widget.update();
172         widget.draw(renderer);
173 
174         // 渲染子组件
175         for child in widget.children().borrow().iter() {
176             self.draw_widget(renderer, child);
177         }
178     }
179 }
180