1 use starry_client::{ 2 base::{ 3 color::Color, 4 renderer::{RenderMode, Renderer}, 5 }, 6 window::Window, 7 }; 8 use std::{ 9 cell::{Cell, RefCell}, 10 fs::File, 11 io::Read, 12 sync::{Arc, Weak}, 13 thread, 14 time::Duration, 15 }; 16 17 use crate::{traits::focus::Focus, util::widget_set_panel, widgets::Widget}; 18 19 use super::{event::Event, rect::Rect}; 20 21 const TTY_DEVICE_PATH: &str = "/dev/char/tty0"; 22 23 const DURATION_TIME: Duration = Duration::from_millis(25); 24 25 /// 面板渲染器 26 pub struct PanelRenderer<'a> { 27 /// 客户端窗口 28 window: &'a mut Window, 29 } 30 31 impl<'a> PanelRenderer<'a> { 32 pub fn new(window: &'a mut Window) -> Self { 33 PanelRenderer { window } 34 } 35 } 36 37 impl<'a> Renderer for PanelRenderer<'a> { 38 fn width(&self) -> u32 { 39 self.window.width() 40 } 41 42 fn height(&self) -> u32 { 43 self.window.height() 44 } 45 46 fn data(&self) -> &[Color] { 47 self.window.data() 48 } 49 50 fn data_mut(&mut self) -> &mut [Color] { 51 self.window.data_mut() 52 } 53 54 fn sync(&mut self) -> bool { 55 self.window.sync() 56 } 57 58 fn mode(&self) -> &Cell<RenderMode> { 59 &self.window.mode() 60 } 61 62 // TODO 63 // fn char(&mut self, x: i32, y: i32, c: char, color: Color) { 64 // } 65 } 66 67 /// UI面板类作为容器管理一组UI组件(UI-Widget) 68 /// 拥有一个窗口对象用于渲染和事件传递 69 pub struct Panel { 70 /// 指向自身的弱引用 71 self_ref: RefCell<Weak<Panel>>, 72 /// 客户端窗口对象 73 window: RefCell<Window>, 74 /// 面板矩形 75 rect: Cell<Rect>, 76 /// 子组件数组 77 widgets: RefCell<Vec<Arc<dyn Widget>>>, 78 /// 窗口是否打开 79 running: Cell<bool>, 80 /// 当前聚焦的窗口 81 focused_widget: RefCell<Option<Arc<dyn Widget>>>, 82 /// 事件数组 83 events: RefCell<Vec<Event>>, 84 /// 需要重绘画面 85 redraw: Cell<bool>, 86 /// tty文件 87 tty_file: RefCell<File>, 88 } 89 90 impl Panel { 91 pub fn new(rect: Rect, title: &str, color: Color) -> Arc<Panel> { 92 Panel::from_window( 93 Window::new(rect.x, rect.y, rect.width, rect.height, title, color), 94 rect, 95 ) 96 } 97 98 pub fn from_window(window: Window, rect: Rect) -> Arc<Panel> { 99 let panel = Arc::new(Panel { 100 self_ref: RefCell::new(Weak::default()), 101 window: RefCell::new(window), 102 rect: Cell::new(rect), 103 widgets: RefCell::new(Vec::new()), 104 running: Cell::new(true), 105 focused_widget: RefCell::new(None), 106 events: RefCell::new(Vec::new()), 107 redraw: Cell::new(false), 108 tty_file: RefCell::new( 109 File::open(TTY_DEVICE_PATH).expect("[Error] Panel failed to open tty file"), 110 ), 111 }); 112 113 (*panel.self_ref.borrow_mut()) = Arc::downgrade(&panel); 114 115 return panel; 116 } 117 118 /// 获得客户端窗口对象 119 pub fn into_window(self) -> Window { 120 self.window.into_inner() 121 } 122 123 /// 返回x坐标 124 pub fn x(&self) -> i32 { 125 let window = self.window.borrow(); 126 (*window).x() 127 } 128 129 /// 返回y坐标 130 pub fn y(&self) -> i32 { 131 let window = self.window.borrow(); 132 (*window).y() 133 } 134 135 /// 返回宽度值 136 pub fn width(&self) -> u32 { 137 let window = self.window.borrow(); 138 (*window).width() 139 } 140 141 /// 返回高度值 142 pub fn height(&self) -> u32 { 143 let window = self.window.borrow(); 144 (*window).height() 145 } 146 147 /// 返回面板矩形 148 pub fn rect(&self) -> Rect { 149 self.rect.get() 150 } 151 152 /// 窗口标题 153 pub fn title(&self) -> String { 154 let window = self.window.borrow(); 155 (*window).title() 156 } 157 158 /// 改变窗口位置 159 pub fn set_pos(&self, x: i32, y: i32) { 160 let mut window = self.window.borrow_mut(); 161 (*window).set_pos(x, y); 162 } 163 164 /// 改变窗口大小 165 pub fn set_size(&self, width: u32, height: u32) { 166 let mut window = self.window.borrow_mut(); 167 (*window).set_size(width, height); 168 } 169 170 /// 改变窗口标题 171 pub fn set_title(&self, title: &str) { 172 let mut window = self.window.borrow_mut(); 173 (*window).set_title(title); 174 } 175 176 /// 关闭窗口 177 pub fn close(&self) { 178 self.running.set(false); 179 } 180 181 /// 添加子组件,返回子组件id 182 pub fn add_child<T: Widget>(&self, widget: &Arc<T>) -> usize { 183 widget_set_panel( 184 &widget.self_ref(), 185 &self.self_ref.borrow().upgrade().unwrap(), 186 ); 187 188 let mut widgets = self.widgets.borrow_mut(); 189 let id = widgets.len(); 190 widgets.push(widget.clone()); 191 widget.arrange_all(); 192 return id; 193 } 194 195 /// 渲染面板(渲染子组件数组) 196 pub fn draw(&self) { 197 let mut window = self.window.borrow_mut(); 198 let mut renderer = PanelRenderer::new(&mut window); 199 200 for widget in self.widgets.borrow().iter() { 201 self.draw_widget(&mut renderer, widget); 202 } 203 204 renderer.sync(); 205 } 206 207 /// 渲染单个组件 208 pub fn draw_widget(&self, renderer: &mut dyn Renderer, widget: &Arc<dyn Widget>) { 209 widget.update(); 210 widget.draw(renderer, self.is_focused(widget)); 211 212 // 渲染子组件 213 for child in widget.children().borrow().iter() { 214 self.draw_widget(renderer, child); 215 } 216 } 217 218 pub fn tick(&self) { 219 // TODO 通过服务器,先从Window对象接收事件,再进行处理 220 self.handle_events(); 221 } 222 223 /// 将事件传递给Widget对象 224 fn handle_events(&self) { 225 while let Some(event) = self.events.borrow_mut().pop() { 226 // 事件是否已被处理 227 let caught = Cell::new(false); 228 229 for widget in self.widgets.borrow().iter().rev() { 230 // TODO 处理返回值 231 widget.handle_event(event, self.is_focused(widget), &self.redraw, &caught); 232 233 if caught.get() { 234 break; 235 } 236 } 237 } 238 } 239 240 // TODO 临时函数 用于客户端直接处理用户输入 241 pub fn push_event(&self, event: Event) { 242 self.events.borrow_mut().push(event); 243 } 244 245 pub fn exec(&self) { 246 while self.running.get() { 247 self.polling_tty(); 248 self.tick(); 249 self.draw_if_needed(); 250 251 thread::sleep(DURATION_TIME); 252 } 253 } 254 255 /// 必要时重绘 256 fn draw_if_needed(&self) { 257 if self.redraw.get() { 258 self.draw(); 259 self.redraw.set(false); 260 } 261 } 262 263 // TODO 临时在客户端做输入读取 后续改为由服务器实现 264 fn polling_tty(&self) { 265 let mut bufffer: [u8; 128] = [0; 128]; 266 let count = self 267 .tty_file 268 .borrow_mut() 269 .read(&mut bufffer) 270 .expect("[Error] Panel failed to read tty file"); 271 for i in 0..count { 272 self.push_event(Event::KeyPressed { 273 character: Some(bufffer[i] as char), 274 }); 275 } 276 } 277 } 278 279 impl Focus for Panel { 280 fn focused_widget(&self) -> RefCell<Option<Arc<dyn Widget>>> { 281 self.focused_widget.clone() 282 } 283 284 fn focus(&self, widget: &Arc<dyn Widget>) { 285 (*self.focused_widget.borrow_mut()) = Some(widget.clone()); 286 } 287 } 288