xref: /StarryEngine/starry_toolkit/src/base/panel.rs (revision b0262857c524418d6bf547b3893cb67126e5df18)
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::{traits::focus::Focus, 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     pub focused_widget: RefCell<Option<Arc<dyn Widget>>>,
77 }
78 
79 impl Panel {
80     pub fn new(rect: Rect, title: &str, color: Color) -> Self {
81         Panel::from_window(Window::new(
82             rect.x,
83             rect.y,
84             rect.width,
85             rect.height,
86             title,
87             color,
88         ))
89     }
90 
91     pub fn from_window(window: Window) -> Self {
92         Panel {
93             window: RefCell::new(window),
94             widgets: RefCell::new(Vec::new()),
95             running: Cell::new(true),
96             focused_widget: RefCell::new(None),
97         }
98     }
99 
100     /// 获得客户端窗口对象
101     pub fn into_window(self) -> Window {
102         self.window.into_inner()
103     }
104 
105     /// 返回x坐标
106     pub fn x(&self) -> i32 {
107         let window = self.window.borrow();
108         (*window).x()
109     }
110 
111     /// 返回y坐标
112     pub fn y(&self) -> i32 {
113         let window = self.window.borrow();
114         (*window).y()
115     }
116 
117     /// 返回宽度值
118     pub fn width(&self) -> u32 {
119         let window = self.window.borrow();
120         (*window).width()
121     }
122 
123     /// 返回高度值
124     pub fn height(&self) -> u32 {
125         let window = self.window.borrow();
126         (*window).height()
127     }
128 
129     /// 窗口标题
130     pub fn title(&self) -> String {
131         let window = self.window.borrow();
132         (*window).title()
133     }
134 
135     /// 改变窗口位置
136     pub fn set_pos(&self, x: i32, y: i32) {
137         let mut window = self.window.borrow_mut();
138         (*window).set_pos(x, y);
139     }
140 
141     /// 改变窗口大小
142     pub fn set_size(&self, width: u32, height: u32) {
143         let mut window = self.window.borrow_mut();
144         (*window).set_size(width, height);
145     }
146 
147     /// 改变窗口标题
148     pub fn set_title(&self, title: &str) {
149         let mut window = self.window.borrow_mut();
150         (*window).set_title(title);
151     }
152 
153     /// 关闭窗口
154     pub fn close(&self) {
155         self.running.set(false);
156     }
157 
158     /// 添加子组件,返回子组件id
159     pub fn add_child<T: Widget>(&self, widget: &Arc<T>) -> usize {
160         let mut widgets = self.widgets.borrow_mut();
161         let id = widgets.len();
162         widgets.push(widget.clone());
163 
164         return id;
165     }
166 
167     /// 渲染面板(渲染子组件数组)
168     pub fn draw(&self) {
169         let mut window = self.window.borrow_mut();
170         let mut renderer = PanelRenderer::new(&mut window);
171 
172         for widget in self.widgets.borrow().iter() {
173             self.draw_widget(&mut renderer, widget);
174         }
175 
176         renderer.sync();
177     }
178 
179     /// 渲染单个组件
180     pub fn draw_widget(&self, renderer: &mut dyn Renderer, widget: &Arc<dyn Widget>) {
181         widget.update();
182         widget.draw(renderer, self.is_focused(widget));
183 
184         // 渲染子组件
185         for child in widget.children().borrow().iter() {
186             self.draw_widget(renderer, child);
187         }
188     }
189 }
190 
191 impl Focus for Panel {
192     fn focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>> {
193         self.focused_widget.clone()
194     }
195 
196     fn focus(&self, widget: &Arc<dyn Widget>) {
197         (*self.focused_widget.borrow_mut()) = Some(widget.clone());
198     }
199 }
200