1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use anyhow::Result;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use fui_core::*;

use crate::DrawingContext;
use crate::Window;

pub struct WindowEntry {
    pub window: Rc<RefCell<Window>>,
    pub services: Rc<RefCell<Services>>,
}

pub struct WindowManager {
    drawing_context: Rc<RefCell<DrawingContext>>,
    main_window_id: Option<winit::window::WindowId>,
    windows: HashMap<winit::window::WindowId, WindowEntry>,
}

impl WindowManager {
    pub fn new(drawing_context: Rc<RefCell<DrawingContext>>) -> Self {
        WindowManager {
            drawing_context: drawing_context,
            main_window_id: None,
            windows: HashMap::new(),
        }
    }

    pub fn add_window(
        &mut self,
        window_builder: winit::window::WindowBuilder,
        event_loop: &winit::event_loop::EventLoop<()>,
        view: Rc<RefCell<dyn ControlObject>>,
    ) -> Result<winit::window::WindowId> {
        let mut window_target = {
            let first_window = self
                .windows
                .iter()
                .next()
                .map(|(_id, entry)| entry.window.clone());

            if let Some(first_window) = first_window {
                self.drawing_context.borrow_mut().create_window(
                    window_builder,
                    &event_loop,
                    Some(&first_window.borrow_mut().drawing_window_target),
                )?
            } else {
                self.drawing_context.borrow_mut().create_window(
                    window_builder,
                    &event_loop,
                    None,
                )?
            }
        };

        let physical_size = window_target.get_window().inner_size();
        let window_id = window_target.get_window().id();

        window_target.update_size(physical_size.width as u16, physical_size.height as u16);
        let window = Window::new(window_target);

        let window_rc = Rc::new(RefCell::new(window));
        let window_service_rc: Rc<RefCell<dyn WindowService>> = window_rc.clone();

        let services = Rc::new(RefCell::new(Services::new(&window_service_rc)));

        view.borrow_mut()
            .get_context_mut()
            .set_services(Some(Rc::downgrade(&services)));
        window_rc.borrow_mut().add_layer(view);

        let window_entry = WindowEntry {
            window: window_rc,
            services: services,
        };
        self.windows.insert(window_id, window_entry);

        if let None = self.main_window_id {
            self.main_window_id = Some(window_id);
        }

        Ok(window_id)
    }

    pub fn add_window_view_model<V: ViewModel>(
        &mut self,
        window_builder: winit::window::WindowBuilder,
        event_loop: &winit::event_loop::EventLoop<()>,
        view_model: &Rc<RefCell<V>>,
    ) -> Result<winit::window::WindowId> {
        self.add_window(
            window_builder,
            &event_loop,
            ViewModel::create_view(&view_model),
        )
    }

    pub fn get_main_window_id(&self) -> Option<winit::window::WindowId> {
        self.main_window_id
    }

    pub fn get_windows_mut(&mut self) -> &mut HashMap<winit::window::WindowId, WindowEntry> {
        &mut self.windows
    }

    pub fn clear(&mut self) {
        self.windows.clear();
        self.main_window_id = None;
    }
}

impl Drop for WindowManager {
    fn drop(&mut self) {
        // It is important to drop windows before drawing_context!
        // Windows cleanup graphics resources and drawing context drops graphics device.
        self.windows.clear();
    }
}