window.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. use std::cell::RefCell;
  2. use std::rc::Rc;
  3. use kahlo::{
  4. math::{PixelBox, PixelPoint, PixelSize},
  5. prelude::*,
  6. };
  7. use crate::input::{InputState, MouseButton};
  8. use crate::layout::{self, LayoutNode, LayoutNodeAccess, LinearAccess};
  9. use crate::widget::Widget;
  10. use crate::{component::Component, ui::UIHandle};
  11. pub type RenderFormat = kahlo::formats::Bgr32;
  12. #[derive(Debug)]
  13. pub enum WindowEvent {
  14. CloseRequested,
  15. Resized,
  16. }
  17. pub trait WindowComponent: 'static + Sized + Component {
  18. fn map_window_event(&self, we: WindowEvent) -> Option<Self::Msg>;
  19. type RootWidget: Widget<Self>;
  20. fn root_widget(&self) -> &Self::RootWidget;
  21. fn root_widget_mut(&mut self) -> &mut Self::RootWidget;
  22. }
  23. pub(crate) struct WindowState<WC: WindowComponent> {
  24. wc: WC,
  25. root_node: LayoutNode,
  26. window: Rc<winit::window::Window>,
  27. events: Vec<WindowEvent>,
  28. istate: InputState,
  29. surface: softbuffer::Surface<Rc<winit::window::Window>, Rc<winit::window::Window>>,
  30. bitmap: RefCell<Option<kahlo::Bitmap<RenderFormat>>>,
  31. }
  32. impl<WC: WindowComponent> WindowState<WC> {
  33. fn redraw(&mut self, uih: &UIHandle) {
  34. let size = self.window.inner_size();
  35. // if size.width != self.surface.buffer_mut().unwrap().
  36. self.surface
  37. .resize(
  38. size.width.try_into().unwrap(),
  39. size.height.try_into().unwrap(),
  40. )
  41. .unwrap();
  42. let mut buf = self.surface.buffer_mut().unwrap();
  43. self.root_node.set_behaviour(layout::NodeBehaviour::Fixed {
  44. area: PixelBox::from_size(PixelSize::new(size.width as i32, size.height as i32)),
  45. });
  46. let layout = LinearAccess::new(&self.root_node, self.wc.root_widget().layout_node());
  47. let mut bitmap = self.bitmap.borrow_mut();
  48. if bitmap.as_ref().map(|v| v.size()) != Some(PixelSize::new(size.width as i32, size.height as i32)) {
  49. bitmap.take();
  50. }
  51. let bitmap = bitmap.get_or_insert_with(|| {
  52. kahlo::Bitmap::new(size.width as usize, size.height as usize)
  53. });
  54. let mut windowbuffer = kahlo::BitmapMut::<kahlo::formats::Bgr32>::new(
  55. unsafe {
  56. std::slice::from_raw_parts_mut(buf[..].as_mut_ptr() as *mut u8, buf.len() * 4)
  57. },
  58. size.width as usize,
  59. size.height as usize,
  60. );
  61. layout::recalculate(LayoutNodeAccess::new(&layout));
  62. let before = std::time::Instant::now();
  63. self.wc.root_widget().render(uih.theme(), &mut bitmap.as_mut());
  64. windowbuffer.copy_from(
  65. bitmap,
  66. PixelBox::from_size(bitmap.size()),
  67. PixelPoint::zero()
  68. );
  69. let after = std::time::Instant::now();
  70. print!("render time: {:?} \r", (after - before));
  71. buf.present().unwrap();
  72. }
  73. fn poll(&mut self, uih: &mut UIHandle) -> Vec<WC::ParentMsg> {
  74. let mut ret = vec![];
  75. for we in self.events.drain(..) {
  76. let mapped = self.wc.map_window_event(we);
  77. ret.extend(self.wc.process_all(mapped.into_iter()).into_iter());
  78. }
  79. let evts = self.wc.root_widget_mut().poll(uih, Some(&self.istate));
  80. ret.extend(self.wc.process_all(evts.into_iter()));
  81. self.istate.tick();
  82. ret
  83. }
  84. }
  85. pub(crate) trait WindowStateAccess {
  86. fn notify_resize(&self, new_size: PixelSize);
  87. fn push_event(&self, we: WindowEvent);
  88. fn redraw(&self, uih: &UIHandle);
  89. fn request_redraw(&self);
  90. fn update_mouse_pos(&self, pos: PixelPoint);
  91. fn update_mouse_button(&self, which: MouseButton, to: bool);
  92. }
  93. impl<WC: WindowComponent> WindowStateAccess for RefCell<WindowState<WC>> {
  94. fn notify_resize(&self, new_size: PixelSize) {
  95. if Some(new_size) != self.borrow().bitmap.borrow().as_ref().map(|v| v.size()) {
  96. self.borrow_mut().bitmap.take();
  97. self.borrow_mut().wc.root_widget().layout_node().relayout_tree();
  98. self.borrow_mut().wc.root_widget().layout_node().render_needed();
  99. }
  100. }
  101. fn push_event(&self, we: WindowEvent) {
  102. self.borrow_mut().events.push(we);
  103. }
  104. fn redraw(&self, uih: &UIHandle) {
  105. self.borrow_mut().redraw(uih);
  106. }
  107. fn request_redraw(&self) {
  108. self.borrow().window.request_redraw();
  109. }
  110. fn update_mouse_pos(&self, pos: PixelPoint) {
  111. self.borrow_mut().istate.mouse.pos = pos;
  112. }
  113. fn update_mouse_button(&self, which: MouseButton, to: bool) {
  114. let is = &mut self.borrow_mut().istate;
  115. is.mouse.buttons.set_button(which, to);
  116. }
  117. }
  118. pub struct WindowBuilder<'r, 'l: 'r> {
  119. ui_handle: &'r mut UIHandle<'l>,
  120. }
  121. impl<'r, 'l: 'r> WindowBuilder<'r, 'l> {
  122. pub(crate) fn new(ui_handle: &'r mut UIHandle<'l>) -> Self {
  123. Self { ui_handle }
  124. }
  125. pub fn build<WC: WindowComponent>(self, wc: impl FnOnce(&mut UIHandle) -> WC) -> Window<WC> {
  126. let window = Rc::new(
  127. self.ui_handle
  128. .eloop
  129. .create_window(winit::window::WindowAttributes::default())
  130. .unwrap(),
  131. );
  132. let wid = window.id();
  133. let ctx = softbuffer::Context::new(window.clone()).unwrap();
  134. let surface = softbuffer::Surface::new(&ctx, window.clone()).unwrap();
  135. let wc = wc(self.ui_handle);
  136. let wstate = Rc::new(RefCell::new(WindowState {
  137. wc,
  138. root_node: LayoutNode::new(self.ui_handle.state.layout_cache.clone()),
  139. window,
  140. events: Default::default(),
  141. istate: InputState::default().into(),
  142. surface: surface.into(),
  143. bitmap: None.into(),
  144. }));
  145. self.ui_handle.state.window_states.insert(
  146. wid,
  147. Rc::downgrade(&(wstate.clone() as Rc<dyn WindowStateAccess>)),
  148. );
  149. Window { state: wstate }
  150. }
  151. }
  152. pub struct Window<WC: WindowComponent> {
  153. state: Rc<RefCell<WindowState<WC>>>,
  154. }
  155. impl<WC: WindowComponent> Window<WC> {
  156. pub fn poll(&mut self, uih: &mut UIHandle) -> Vec<WC::ParentMsg> {
  157. self.state.borrow_mut().poll(uih)
  158. }
  159. }