Skip to main content

blitz_traits/
shell.rs

1//! Abstraction over windowing / operating system ("shell") functionality
2
3use cursor_icon::CursorIcon;
4
5/// Type representing an error performing a clipboard operation
6// TODO: fill out with meaningful errors
7pub struct ClipboardError;
8
9/// Abstraction over windowing / operating system ("shell") functionality that allows a Blitz document
10/// to access that functionality without depending on a specific shell environment.
11pub trait ShellProvider: Send + Sync + 'static {
12    fn request_redraw(&self) {}
13    fn set_cursor(&self, icon: Option<CursorIcon>) {
14        let _ = icon;
15    }
16    fn set_window_title(&self, title: String) {
17        let _ = title;
18    }
19    fn set_ime_enabled(&self, is_enabled: bool) {
20        let _ = is_enabled;
21    }
22    fn set_ime_cursor_area(&self, x: f32, y: f32, width: f32, height: f32) {
23        let _ = x;
24        let _ = y;
25        let _ = width;
26        let _ = height;
27    }
28    fn get_clipboard_text(&self) -> Result<String, ClipboardError> {
29        Err(ClipboardError)
30    }
31    fn set_clipboard_text(&self, text: String) -> Result<(), ClipboardError> {
32        let _ = text;
33        Err(ClipboardError)
34    }
35    /// Put a selection on the clipboard as both rich text and plain text.
36    ///
37    /// Two payloads, one copy. A target that understands HTML takes the markup
38    /// and keeps the bold, the links and the code spans; everything else takes
39    /// `text`, which is what a plain `set_clipboard_text` would have written on
40    /// its own. Pasting formatted text out of a Blitz window was impossible
41    /// before this, because plain text was the only thing ever offered.
42    ///
43    /// Defaults to the plain path so a shell that has not implemented it still
44    /// copies, rather than silently putting nothing on the clipboard.
45    fn set_clipboard_html(&self, html: String, text: String) -> Result<(), ClipboardError> {
46        let _ = html;
47        self.set_clipboard_text(text)
48    }
49    fn open_file_dialog(
50        &self,
51        multiple: bool,
52        filter: Option<FileDialogFilter>,
53    ) -> Vec<std::path::PathBuf> {
54        let _ = multiple;
55        let _ = filter;
56        vec![]
57    }
58
59    // Window chrome controls, for documents that draw their own titlebar
60    // (e.g. a frameless window with an HTML titlebar).
61    fn request_window_close(&self) {}
62    fn set_window_minimized(&self, minimized: bool) {
63        let _ = minimized;
64    }
65    fn set_window_maximized(&self, maximized: bool) {
66        let _ = maximized;
67    }
68    fn is_window_maximized(&self) -> bool {
69        false
70    }
71    fn set_window_decorations(&self, decorations: bool) {
72        let _ = decorations;
73    }
74    /// Begin an interactive user-driven move of the window (call from a
75    /// mousedown handler on a drag region)
76    fn drag_window(&self) {}
77}
78
79pub struct DummyShellProvider;
80impl ShellProvider for DummyShellProvider {}
81
82/// The system color scheme (light and dark mode)
83#[derive(Default, Debug, Clone, Copy, PartialEq)]
84pub enum ColorScheme {
85    #[default]
86    Light,
87    Dark,
88}
89
90#[derive(Debug, Clone, PartialEq)]
91pub struct Viewport {
92    pub color_scheme: ColorScheme,
93    pub window_size: (u32, u32),
94    pub hidpi_scale: f32,
95    pub zoom: f32,
96}
97
98impl Default for Viewport {
99    fn default() -> Self {
100        Self {
101            window_size: (0, 0),
102            hidpi_scale: 1.0,
103            zoom: 1.0,
104            color_scheme: ColorScheme::Light,
105        }
106    }
107}
108
109impl Viewport {
110    pub fn new(
111        physical_width: u32,
112        physical_height: u32,
113        scale_factor: f32,
114        color_scheme: ColorScheme,
115    ) -> Self {
116        Self {
117            window_size: (physical_width, physical_height),
118            hidpi_scale: scale_factor,
119            zoom: 1.0,
120            color_scheme,
121        }
122    }
123
124    /// Total scaling, computed as `hidpi_scale_factor * zoom`
125    pub fn scale(&self) -> f32 {
126        self.hidpi_scale * self.zoom
127    }
128    /// Same as [`scale`](Self::scale) but `f64` instead of `f32`
129    pub fn scale_f64(&self) -> f64 {
130        self.scale() as f64
131    }
132
133    /// Set hidpi scale factor
134    pub fn set_hidpi_scale(&mut self, scale: f32) {
135        self.hidpi_scale = scale;
136    }
137
138    /// Get document zoom level
139    pub fn zoom(&self) -> f32 {
140        self.zoom
141    }
142
143    /// Set document zoom level (`1.0` is unzoomed)
144    pub fn set_zoom(&mut self, zoom: f32) {
145        self.zoom = zoom;
146    }
147
148    pub fn zoom_by(&mut self, zoom: f32) {
149        self.zoom += zoom;
150    }
151
152    pub fn zoom_mut(&mut self) -> &mut f32 {
153        &mut self.zoom
154    }
155}
156
157/// Filter provided by the dom for an file picker
158pub struct FileDialogFilter {
159    pub name: String,
160    pub extensions: Vec<String>,
161}