|
@@ -1,8 +1,8 @@
|
|
|
pub mod component;
|
|
|
-// pub mod geom;
|
|
|
pub mod input;
|
|
|
pub mod layout;
|
|
|
-// pub mod platform;
|
|
|
+pub mod text;
|
|
|
+pub mod ui;
|
|
|
pub mod widget;
|
|
|
pub mod window;
|
|
|
|
|
@@ -10,214 +10,3 @@ pub mod prelude {
|
|
|
pub use crate::component::Component;
|
|
|
pub use crate::widget::Widget;
|
|
|
}
|
|
|
-use std::collections::HashMap;
|
|
|
-
|
|
|
-use prelude::*;
|
|
|
-
|
|
|
-#[derive(Debug)]
|
|
|
-pub enum UIControlMsg {
|
|
|
- Terminate,
|
|
|
-}
|
|
|
-
|
|
|
-pub trait UIComponent: Sized + component::Component<ParentMsg = UIControlMsg> {
|
|
|
- fn init(&mut self, ui_handle: UIHandle);
|
|
|
- fn poll(&mut self) -> Vec<UIControlMsg>;
|
|
|
- // fn build(bc: &widget::BuildContext) -> Self;
|
|
|
- // fn map_ui_event(&self, uievent: platform::event::UIEvent) -> Option<Self::Msg>;
|
|
|
-}
|
|
|
-
|
|
|
-pub(crate) struct UIState {
|
|
|
- pub(crate) layout_cache: std::rc::Rc<layout::LayoutCache>,
|
|
|
- pub(crate) window_states:
|
|
|
- HashMap<winit::window::WindowId, std::rc::Weak<dyn window::WindowStateAccess>>,
|
|
|
-}
|
|
|
-
|
|
|
-pub struct UIHandle<'l> {
|
|
|
- state: &'l mut UIState,
|
|
|
- eloop: &'l winit::event_loop::ActiveEventLoop,
|
|
|
-}
|
|
|
-
|
|
|
-impl<'l> UIHandle<'l> {
|
|
|
- pub fn window_builder<'r>(&'r mut self) -> window::WindowBuilder<'r, 'l> {
|
|
|
- window::WindowBuilder::new(self)
|
|
|
- }
|
|
|
-
|
|
|
- pub fn new_layout_node(&self) -> layout::LayoutNode {
|
|
|
- layout::LayoutNode::new(self.state.layout_cache.clone())
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-pub struct UI<UIC: UIComponent> {
|
|
|
- state: UIState,
|
|
|
- event_loop: Option<winit::event_loop::EventLoop<()>>,
|
|
|
- ui_component: UIC,
|
|
|
- autoclose: bool,
|
|
|
- initialized: bool,
|
|
|
-}
|
|
|
-
|
|
|
-impl<UIC: UIComponent> UI<UIC> {
|
|
|
- pub fn new(uic: UIC) -> Self {
|
|
|
- let lcache = layout::LayoutCache::new();
|
|
|
-
|
|
|
- let eloop = winit::event_loop::EventLoop::builder().build().unwrap();
|
|
|
- eloop.set_control_flow(winit::event_loop::ControlFlow::Wait);
|
|
|
-
|
|
|
- Self {
|
|
|
- state: UIState {
|
|
|
- layout_cache: lcache,
|
|
|
- window_states: Default::default(),
|
|
|
- },
|
|
|
- event_loop: Some(eloop),
|
|
|
- // root_layout_node: layout::LayoutNode::new(lcache.clone()),
|
|
|
- ui_component: uic,
|
|
|
- autoclose: true,
|
|
|
- initialized: false,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pub fn disable_autoclose(mut self) -> Self {
|
|
|
- self.autoclose = false;
|
|
|
- self
|
|
|
- }
|
|
|
-
|
|
|
- pub fn ui_component(&self) -> &UIC {
|
|
|
- &self.ui_component
|
|
|
- }
|
|
|
- pub fn ui_component_mut(&mut self) -> &mut UIC {
|
|
|
- &mut self.ui_component
|
|
|
- }
|
|
|
-
|
|
|
- /// Public helper function, delivers a message to the UI component and then processes whatever
|
|
|
- /// control messages result.
|
|
|
- pub fn deliver_msg(&mut self, msg: UIC::Msg) {
|
|
|
- let cmsgs = self.ui_component.process(msg);
|
|
|
- self.process_control_msgs(cmsgs.into_iter());
|
|
|
- }
|
|
|
-
|
|
|
- fn process_control_msgs(&mut self, msgs: impl Iterator<Item = UIControlMsg>) {
|
|
|
- for cmsg in msgs {
|
|
|
- match cmsg {
|
|
|
- UIControlMsg::Terminate => {
|
|
|
- todo!()
|
|
|
- // self.ui_running = false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pub fn update(&mut self) {
|
|
|
- /*
|
|
|
- let mut platform_events = vec![];
|
|
|
- while let Some(evt) = self.platform.poll_event() {
|
|
|
- match evt {
|
|
|
- platform::event::WindowEvent::CloseRequest => {
|
|
|
- platform_events.extend(
|
|
|
- self.ui_component()
|
|
|
- .map_ui_event(platform::event::UIEvent::Shutdown)
|
|
|
- .into_iter(),
|
|
|
- );
|
|
|
- }
|
|
|
- _ => {}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // poll for state changes due to user input
|
|
|
- let poll_msgs = self
|
|
|
- .ui_component
|
|
|
- .root_widget_mut()
|
|
|
- .poll(Some(&self.input_state))
|
|
|
- .into_iter();
|
|
|
- let cmsgs = self
|
|
|
- .ui_component
|
|
|
- .process_all(platform_events.into_iter().chain(poll_msgs));
|
|
|
- self.process_control_msgs(cmsgs.into_iter());
|
|
|
-
|
|
|
- let tgt_size = self.platform.render_size();
|
|
|
- self.root_layout_node
|
|
|
- .set_behaviour(layout::NodeBehaviour::Fixed {
|
|
|
- rect: geom::IRect::new_from_size(geom::IPoint::ORIGIN, tgt_size),
|
|
|
- });
|
|
|
- */
|
|
|
-
|
|
|
- // first, make sure we can paint to the render target
|
|
|
- /*
|
|
|
- let (ri, ti) = self.platform.render_text_mut();
|
|
|
- if let Some(mut painter) = ri.render_target_mut().painter() {
|
|
|
- // perform layout as needed
|
|
|
- layout::recalculate(LayoutNodeAccess::new(&layout::LinearAccess::new(
|
|
|
- &self.root_layout_node,
|
|
|
- self.ui_component.root_widget().layout_node(),
|
|
|
- )));
|
|
|
-
|
|
|
- // now render as needed
|
|
|
- self.ui_component.root_widget().render(&mut painter, ti);
|
|
|
- } else {
|
|
|
- log::warn!("Could not draw UI: no painter available");
|
|
|
- }
|
|
|
- ri.submit();
|
|
|
- */
|
|
|
- }
|
|
|
-
|
|
|
- pub fn wait(&mut self) {
|
|
|
- // self.platform.event_mut().wait_for_event();
|
|
|
- }
|
|
|
-
|
|
|
- pub fn run(mut self) {
|
|
|
- let eloop = self.event_loop.take().unwrap();
|
|
|
- eloop.run_app(&mut self).unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- fn pump_events(&mut self, eloop: &winit::event_loop::ActiveEventLoop) {
|
|
|
- let evts = self.ui_component.poll();
|
|
|
- for evt in evts.into_iter() {
|
|
|
- match evt {
|
|
|
- UIControlMsg::Terminate => eloop.exit(),
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl<UIC: UIComponent> winit::application::ApplicationHandler<()> for UI<UIC> {
|
|
|
- fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
|
|
- if !self.initialized {
|
|
|
- self.ui_component.init(UIHandle {
|
|
|
- eloop: event_loop,
|
|
|
- state: &mut self.state,
|
|
|
- });
|
|
|
- self.initialized = true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fn window_event(
|
|
|
- &mut self,
|
|
|
- event_loop: &winit::event_loop::ActiveEventLoop,
|
|
|
- window_id: winit::window::WindowId,
|
|
|
- event: winit::event::WindowEvent,
|
|
|
- ) {
|
|
|
- let Some(wsa) = self
|
|
|
- .state
|
|
|
- .window_states
|
|
|
- .get(&window_id)
|
|
|
- .map(std::rc::Weak::upgrade)
|
|
|
- .flatten()
|
|
|
- else {
|
|
|
- println!("superfluous event: {event:?}");
|
|
|
- return;
|
|
|
- };
|
|
|
-
|
|
|
- match event {
|
|
|
- winit::event::WindowEvent::CloseRequested => {
|
|
|
- wsa.push_event(window::WindowEvent::CloseRequested);
|
|
|
- self.pump_events(event_loop);
|
|
|
- }
|
|
|
- winit::event::WindowEvent::Destroyed => {
|
|
|
- self.state.window_states.remove(&window_id);
|
|
|
- }
|
|
|
- winit::event::WindowEvent::RedrawRequested => {
|
|
|
- wsa.request_redraw();
|
|
|
- self.pump_events(event_loop);
|
|
|
- }
|
|
|
- _ => (),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|