diff options
author | 2022-09-21 19:37:28 -0300 | |
---|---|---|
committer | 2023-01-09 11:27:04 -0800 | |
commit | ce43514eaca0e892ad2f646a63fc29af2150d79c (patch) | |
tree | 1034d5503a458904b3c996ac9e2be64319d484a3 /glutin/src/multi_window/state.rs | |
parent | 064407635a0f9d79a067bad62f6f1042acaed18d (diff) | |
download | iced-ce43514eaca0e892ad2f646a63fc29af2150d79c.tar.gz iced-ce43514eaca0e892ad2f646a63fc29af2150d79c.tar.bz2 iced-ce43514eaca0e892ad2f646a63fc29af2150d79c.zip |
copy `multi_window::Event` from `iced_winit`
Diffstat (limited to 'glutin/src/multi_window/state.rs')
-rw-r--r-- | glutin/src/multi_window/state.rs | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/glutin/src/multi_window/state.rs b/glutin/src/multi_window/state.rs new file mode 100644 index 00000000..163f46bd --- /dev/null +++ b/glutin/src/multi_window/state.rs @@ -0,0 +1,241 @@ +use crate::application::{self, StyleSheet as _}; +use crate::conversion; +use crate::multi_window::{Application, Event}; +use crate::window; +use crate::{Color, Debug, Point, Size, Viewport}; + +use glutin::event::{Touch, WindowEvent}; +use glutin::event_loop::EventLoopProxy; +use glutin::window::Window; +use std::collections::HashMap; +use std::marker::PhantomData; + +/// The state of a windowed [`Application`]. +#[allow(missing_debug_implementations)] +pub struct State<A: Application> +where + <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +{ + title: String, + scale_factor: f64, + viewport: Viewport, + viewport_changed: bool, + cursor_position: glutin::dpi::PhysicalPosition<f64>, + modifiers: glutin::event::ModifiersState, + theme: <A::Renderer as crate::Renderer>::Theme, + appearance: iced_winit::application::Appearance, + application: PhantomData<A>, +} + +impl<A: Application> State<A> +where + <A::Renderer as crate::Renderer>::Theme: application::StyleSheet, +{ + /// Creates a new [`State`] for the provided [`Application`] and window. + pub fn new(application: &A, window: &Window) -> Self { + let title = application.title(); + let scale_factor = application.scale_factor(); + let theme = application.theme(); + let appearance = theme.appearance(application.style()); + + let viewport = { + let physical_size = window.inner_size(); + + Viewport::with_physical_size( + Size::new(physical_size.width, physical_size.height), + window.scale_factor() * scale_factor, + ) + }; + + Self { + title, + scale_factor, + viewport, + viewport_changed: false, + // TODO: Encode cursor availability in the type-system + cursor_position: glutin::dpi::PhysicalPosition::new(-1.0, -1.0), + modifiers: glutin::event::ModifiersState::default(), + theme, + appearance, + application: PhantomData, + } + } + + /// Returns the current [`Viewport`] of the [`State`]. + pub fn viewport(&self) -> &Viewport { + &self.viewport + } + + /// TODO(derezzedex) + pub fn viewport_changed(&self) -> bool { + self.viewport_changed + } + + /// Returns the physical [`Size`] of the [`Viewport`] of the [`State`]. + pub fn physical_size(&self) -> Size<u32> { + self.viewport.physical_size() + } + + /// Returns the logical [`Size`] of the [`Viewport`] of the [`State`]. + pub fn logical_size(&self) -> Size<f32> { + self.viewport.logical_size() + } + + /// Returns the current scale factor of the [`Viewport`] of the [`State`]. + pub fn scale_factor(&self) -> f64 { + self.viewport.scale_factor() + } + + /// Returns the current cursor position of the [`State`]. + pub fn cursor_position(&self) -> Point { + conversion::cursor_position( + self.cursor_position, + self.viewport.scale_factor(), + ) + } + + /// Returns the current keyboard modifiers of the [`State`]. + pub fn modifiers(&self) -> glutin::event::ModifiersState { + self.modifiers + } + + /// Returns the current theme of the [`State`]. + pub fn theme(&self) -> &<A::Renderer as crate::Renderer>::Theme { + &self.theme + } + + /// Returns the current background [`Color`] of the [`State`]. + pub fn background_color(&self) -> Color { + self.appearance.background_color + } + + /// Returns the current text [`Color`] of the [`State`]. + pub fn text_color(&self) -> Color { + self.appearance.text_color + } + + /// Processes the provided window event and updates the [`State`] + /// accordingly. + pub fn update( + &mut self, + window: &Window, + event: &WindowEvent<'_>, + _debug: &mut Debug, + ) { + match event { + WindowEvent::Resized(new_size) => { + let size = Size::new(new_size.width, new_size.height); + + self.viewport = Viewport::with_physical_size( + size, + window.scale_factor() * self.scale_factor, + ); + + self.viewport_changed = true; + } + WindowEvent::ScaleFactorChanged { + scale_factor: new_scale_factor, + new_inner_size, + } => { + let size = + Size::new(new_inner_size.width, new_inner_size.height); + + self.viewport = Viewport::with_physical_size( + size, + new_scale_factor * self.scale_factor, + ); + + self.viewport_changed = true; + } + WindowEvent::CursorMoved { position, .. } + | WindowEvent::Touch(Touch { + location: position, .. + }) => { + self.cursor_position = *position; + } + WindowEvent::CursorLeft { .. } => { + // TODO: Encode cursor availability in the type-system + self.cursor_position = + glutin::dpi::PhysicalPosition::new(-1.0, -1.0); + } + WindowEvent::ModifiersChanged(new_modifiers) => { + self.modifiers = *new_modifiers; + } + #[cfg(feature = "debug")] + WindowEvent::KeyboardInput { + input: + glutin::event::KeyboardInput { + virtual_keycode: + Some(glutin::event::VirtualKeyCode::F12), + state: glutin::event::ElementState::Pressed, + .. + }, + .. + } => _debug.toggle(), + _ => {} + } + } + + /// Synchronizes the [`State`] with its [`Application`] and its respective + /// window. + /// + /// Normally an [`Application`] should be synchronized with its [`State`] + /// and window after calling [`Application::update`]. + /// + /// [`Application::update`]: crate::Program::update + pub fn synchronize( + &mut self, + application: &A, + windows: &HashMap<window::Id, Window>, + proxy: &EventLoopProxy<Event<A::Message>>, + ) { + let new_windows = application.windows(); + + // Check for windows to close + for window_id in windows.keys() { + if !new_windows.iter().any(|(id, _)| id == window_id) { + proxy + .send_event(Event::CloseWindow(*window_id)) + .expect("Failed to send message"); + } + } + + // Check for windows to spawn + for (id, settings) in new_windows { + if !windows.contains_key(&id) { + proxy + .send_event(Event::NewWindow(id, settings)) + .expect("Failed to send message"); + } + } + + let window = windows.values().next().expect("No window found"); + + // Update window title + let new_title = application.title(); + + if self.title != new_title { + window.set_title(&new_title); + + self.title = new_title; + } + + // Update scale factor + let new_scale_factor = application.scale_factor(); + + if self.scale_factor != new_scale_factor { + let size = window.inner_size(); + + self.viewport = Viewport::with_physical_size( + Size::new(size.width, size.height), + window.scale_factor() * new_scale_factor, + ); + + self.scale_factor = new_scale_factor; + } + + // Update theme and appearance + self.theme = application.theme(); + self.appearance = self.theme.appearance(application.style()); + } +} |