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