panel.rs 6.8 KB

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