iced_winit/window/
state.rs
1use crate::conversion;
2use crate::core::{Color, Size};
3use crate::core::{mouse, theme, window};
4use crate::graphics::Viewport;
5use crate::program::{self, Program};
6
7use winit::event::{Touch, WindowEvent};
8use winit::window::Window;
9
10use std::fmt::{Debug, Formatter};
11
12pub struct State<P: Program>
14where
15 P::Theme: theme::Base,
16{
17 title: String,
18 scale_factor: f64,
19 viewport: Viewport,
20 viewport_version: u64,
21 cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
22 modifiers: winit::keyboard::ModifiersState,
23 theme: P::Theme,
24 style: theme::Style,
25}
26
27impl<P: Program> Debug for State<P>
28where
29 P::Theme: theme::Base,
30{
31 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
32 f.debug_struct("multi_window::State")
33 .field("title", &self.title)
34 .field("scale_factor", &self.scale_factor)
35 .field("viewport", &self.viewport)
36 .field("viewport_version", &self.viewport_version)
37 .field("cursor_position", &self.cursor_position)
38 .field("style", &self.style)
39 .finish()
40 }
41}
42
43impl<P: Program> State<P>
44where
45 P::Theme: theme::Base,
46{
47 pub fn new(
49 program: &program::Instance<P>,
50 window_id: window::Id,
51 window: &Window,
52 ) -> Self {
53 let title = program.title(window_id);
54 let scale_factor = program.scale_factor(window_id);
55 let theme = program.theme(window_id);
56 let style = program.style(&theme);
57
58 let viewport = {
59 let physical_size = window.inner_size();
60
61 Viewport::with_physical_size(
62 Size::new(physical_size.width, physical_size.height),
63 window.scale_factor() * scale_factor,
64 )
65 };
66
67 Self {
68 title,
69 scale_factor,
70 viewport,
71 viewport_version: 0,
72 cursor_position: None,
73 modifiers: winit::keyboard::ModifiersState::default(),
74 theme,
75 style,
76 }
77 }
78
79 pub fn viewport(&self) -> &Viewport {
81 &self.viewport
82 }
83
84 pub fn viewport_version(&self) -> u64 {
88 self.viewport_version
89 }
90
91 pub fn physical_size(&self) -> Size<u32> {
93 self.viewport.physical_size()
94 }
95
96 pub fn logical_size(&self) -> Size<f32> {
98 self.viewport.logical_size()
99 }
100
101 pub fn scale_factor(&self) -> f64 {
103 self.viewport.scale_factor()
104 }
105
106 pub fn cursor(&self) -> mouse::Cursor {
108 self.cursor_position
109 .map(|cursor_position| {
110 conversion::cursor_position(
111 cursor_position,
112 self.viewport.scale_factor(),
113 )
114 })
115 .map(mouse::Cursor::Available)
116 .unwrap_or(mouse::Cursor::Unavailable)
117 }
118
119 pub fn modifiers(&self) -> winit::keyboard::ModifiersState {
121 self.modifiers
122 }
123
124 pub fn theme(&self) -> &P::Theme {
126 &self.theme
127 }
128
129 pub fn background_color(&self) -> Color {
131 self.style.background_color
132 }
133
134 pub fn text_color(&self) -> Color {
136 self.style.text_color
137 }
138
139 pub fn update(&mut self, window: &Window, event: &WindowEvent) {
141 match event {
142 WindowEvent::Resized(new_size) => {
143 let size = Size::new(new_size.width, new_size.height);
144
145 self.viewport = Viewport::with_physical_size(
146 size,
147 window.scale_factor() * self.scale_factor,
148 );
149
150 self.viewport_version = self.viewport_version.wrapping_add(1);
151 }
152 WindowEvent::ScaleFactorChanged {
153 scale_factor: new_scale_factor,
154 ..
155 } => {
156 let size = self.viewport.physical_size();
157
158 self.viewport = Viewport::with_physical_size(
159 size,
160 new_scale_factor * self.scale_factor,
161 );
162
163 self.viewport_version = self.viewport_version.wrapping_add(1);
164 }
165 WindowEvent::CursorMoved { position, .. }
166 | WindowEvent::Touch(Touch {
167 location: position, ..
168 }) => {
169 self.cursor_position = Some(*position);
170 }
171 WindowEvent::CursorLeft { .. } => {
172 self.cursor_position = None;
173 }
174 WindowEvent::ModifiersChanged(new_modifiers) => {
175 self.modifiers = new_modifiers.state();
176 }
177 _ => {}
178 }
179 }
180
181 pub fn synchronize(
187 &mut self,
188 program: &program::Instance<P>,
189 window_id: window::Id,
190 window: &Window,
191 ) {
192 let new_title = program.title(window_id);
194
195 if self.title != new_title {
196 window.set_title(&new_title);
197 self.title = new_title;
198 }
199
200 let new_scale_factor = program.scale_factor(window_id);
202 let new_size = window.inner_size();
203 let current_size = self.viewport.physical_size();
204
205 if self.scale_factor != new_scale_factor
206 || (current_size.width, current_size.height)
207 != (new_size.width, new_size.height)
208 {
209 self.viewport = Viewport::with_physical_size(
210 Size::new(new_size.width, new_size.height),
211 window.scale_factor() * new_scale_factor,
212 );
213 self.viewport_version = self.viewport_version.wrapping_add(1);
214
215 self.scale_factor = new_scale_factor;
216 }
217
218 self.theme = program.theme(window_id);
220 self.style = program.style(&self.theme);
221 }
222}