pytauri_core/ext_mod_impl/lib/
rect.rs

1use pyo3::{prelude::*, types::PyTuple};
2
3/// See also: [tauri::Rect]
4#[pyclass(frozen)]
5pub struct Rect {
6    // use `Py<T>` to avoid creating new obj every time visiting the field,
7    // see: <https://pyo3.rs/v0.23.4/faq.html#pyo3get-clones-my-field>
8    #[pyo3(get)]
9    pub position: Py<Position>,
10    #[pyo3(get)]
11    pub size: Py<Size>,
12}
13
14impl Rect {
15    pub(crate) fn from_tauri(py: Python<'_>, rect: tauri::Rect) -> PyResult<Self> {
16        let position = Position::from_tauri(py, rect.position)?
17            .into_pyobject(py)?
18            .unbind();
19        let size = Size::from_tauri(py, rect.size)?.into_pyobject(py)?.unbind();
20        Ok(Self { position, size })
21    }
22
23    #[expect(dead_code)] // TODO
24    pub(crate) fn to_tauri(&self, py: Python<'_>) -> PyResult<tauri::Rect> {
25        let ret = tauri::Rect {
26            position: self.position.get().to_tauri(py)?,
27            size: self.size.get().to_tauri(py)?,
28        };
29        Ok(ret)
30    }
31}
32
33#[pymethods]
34impl Rect {
35    #[new]
36    #[pyo3(signature = (*, position, size))]
37    fn __new__(position: Py<Position>, size: Py<Size>) -> Self {
38        Self { position, size }
39    }
40}
41
42pub(crate) type TauriPhysicalRect = tauri::PhysicalRect<i32, u32>;
43
44/// See also: [tauri::PhysicalRect]
45#[pyclass(frozen)]
46pub struct PhysicalRect {
47    #[pyo3(get)]
48    #[expect(private_interfaces)]
49    pub position: PhysicalPositionI32,
50    #[pyo3(get)]
51    #[expect(private_interfaces)]
52    pub size: PhysicalSizeU32,
53}
54
55impl PhysicalRect {
56    pub(crate) fn from_tauri(py: Python<'_>, rect: TauriPhysicalRect) -> PyResult<Self> {
57        let position = PhysicalPositionI32::from_tauri(py, rect.position)?;
58        let size = PhysicalSizeU32::from_tauri(py, rect.size)?;
59        Ok(Self { position, size })
60    }
61
62    #[expect(dead_code)] // TODO
63    pub(crate) fn to_tauri(&self, py: Python<'_>) -> PyResult<TauriPhysicalRect> {
64        let ret = TauriPhysicalRect {
65            position: self.position.to_tauri(py)?,
66            size: self.size.to_tauri(py)?,
67        };
68        Ok(ret)
69    }
70}
71
72#[pymethods]
73impl PhysicalRect {
74    #[new]
75    #[pyo3(signature = (*, position, size))]
76    fn __new__(position: PhysicalPositionI32, size: PhysicalSizeU32) -> Self {
77        Self { position, size }
78    }
79}
80
81pub(crate) type TauriLogicalRect = tauri::LogicalRect<f64, f64>;
82
83/// See also: [tauri::LogicalRect]
84#[pyclass(frozen)]
85pub struct LogicalRect {
86    #[pyo3(get)]
87    #[expect(private_interfaces)]
88    pub position: LogicalPositionF64,
89    #[pyo3(get)]
90    #[expect(private_interfaces)]
91    pub size: LogicalSizeF64,
92}
93
94impl LogicalRect {
95    #[expect(dead_code)] // TODO
96    pub(crate) fn from_tauri(py: Python<'_>, rect: TauriLogicalRect) -> PyResult<Self> {
97        let position = LogicalPositionF64::from_tauri(py, rect.position)?;
98        let size = LogicalSizeF64::from_tauri(py, rect.size)?;
99        Ok(Self { position, size })
100    }
101
102    #[expect(dead_code)] // TODO
103    pub(crate) fn to_tauri(&self, py: Python<'_>) -> PyResult<TauriLogicalRect> {
104        let ret = TauriLogicalRect {
105            position: self.position.to_tauri(py)?,
106            size: self.size.to_tauri(py)?,
107        };
108        Ok(ret)
109    }
110}
111
112#[pymethods]
113impl LogicalRect {
114    #[new]
115    #[pyo3(signature = (*, position, size))]
116    fn __new__(position: LogicalPositionF64, size: LogicalSizeF64) -> Self {
117        Self { position, size }
118    }
119}
120
121/// See also: [tauri::Position]
122#[pyclass(frozen)]
123pub enum Position {
124    #[expect(private_interfaces)]
125    Physical(PhysicalPositionI32),
126    #[expect(private_interfaces)]
127    Logical(LogicalPositionF64),
128}
129
130impl Position {
131    pub(crate) fn from_tauri(py: Python<'_>, position: tauri::Position) -> PyResult<Self> {
132        let ret = match position {
133            tauri::Position::Physical(pos) => {
134                Position::Physical(PhysicalPositionI32::from_tauri(py, pos)?)
135            }
136            tauri::Position::Logical(pos) => {
137                Position::Logical(LogicalPositionF64::from_tauri(py, pos)?)
138            }
139        };
140        Ok(ret)
141    }
142
143    pub(crate) fn to_tauri(&self, py: Python<'_>) -> PyResult<tauri::Position> {
144        match self {
145            Position::Physical(pos) => pos.to_tauri(py).map(tauri::Position::Physical),
146            Position::Logical(pos) => pos.to_tauri(py).map(tauri::Position::Logical),
147        }
148    }
149}
150
151/// See also: [tauri::Size]
152#[pyclass(frozen)]
153pub enum Size {
154    #[expect(private_interfaces)]
155    Physical(PhysicalSizeU32),
156    #[expect(private_interfaces)]
157    Logical(LogicalSizeF64),
158}
159
160impl Size {
161    pub(crate) fn from_tauri(py: Python<'_>, size: tauri::Size) -> PyResult<Self> {
162        let ret = match size {
163            tauri::Size::Physical(size) => Size::Physical(PhysicalSizeU32::from_tauri(py, size)?),
164            tauri::Size::Logical(size) => Size::Logical(LogicalSizeF64::from_tauri(py, size)?),
165        };
166        Ok(ret)
167    }
168
169    pub(crate) fn to_tauri(&self, py: Python<'_>) -> PyResult<tauri::Size> {
170        match self {
171            Size::Physical(size) => size.to_tauri(py).map(tauri::Size::Physical),
172            Size::Logical(size) => size.to_tauri(py).map(tauri::Size::Logical),
173        }
174    }
175}
176
177macro_rules! position {
178    ($vis:vis, $name:ident, $ty:ty => $from_tauri:ident, $to_tauri:ident, $tauri_ty:ty) => {
179        /// See also: [tauri::PhysicalPosition] and [tauri::LogicalPosition]
180        ///
181        /// `(x, y)`
182        #[derive(FromPyObject, IntoPyObject, IntoPyObjectRef)]
183        #[pyo3(transparent)]
184        $vis struct $name($vis Py<PyTuple>);
185
186        impl $name {
187            #[allow(dead_code)]
188            $vis fn $from_tauri(
189                py: Python<'_>,
190                value: $tauri_ty,
191            ) -> PyResult<Self> {
192                let x_y: ($ty, $ty) = (value.x, value.y); // typing assertion
193                Ok(Self(x_y.into_pyobject(py)?.unbind()))
194            }
195
196            #[allow(dead_code)]
197            $vis fn $to_tauri(
198                &self,
199                py: Python<'_>,
200            ) -> PyResult<$tauri_ty> {
201                let (x, y): ($ty, $ty) = self.0.extract(py)?;
202                type TauriTy = $tauri_ty; // convert to expr `TauriTy`
203                Ok(TauriTy { x, y })
204            }
205        }
206    };
207}
208
209macro_rules! size {
210    ($vis:vis, $name:ident, $ty:ty => $from_tauri:ident, $to_tauri:ident, $tauri_ty:ty) => {
211        /// See also: [tauri::PhysicalSize] and [tauri::LogicalSize]
212        ///
213        /// `(width, height)`
214        #[derive(FromPyObject, IntoPyObject, IntoPyObjectRef)]
215        #[pyo3(transparent)]
216        $vis struct $name($vis Py<PyTuple>);
217
218        impl $name {
219            #[allow(dead_code)]
220            $vis fn $from_tauri(
221                py: Python<'_>,
222                value: $tauri_ty,
223            ) -> PyResult<Self> {
224                let width_height: ($ty, $ty) = (value.width, value.height); // typing assertion
225                Ok(Self(width_height.into_pyobject(py)?.unbind()))
226            }
227
228            #[allow(dead_code)]
229            $vis fn $to_tauri(
230                &self,
231                py: Python<'_>,
232            ) -> PyResult<$tauri_ty> {
233                let (width, height): ($ty, $ty) = self.0.extract(py)?;
234                type TauriTy = $tauri_ty; // convert to expr `TauriTy`
235                Ok(TauriTy { width, height })
236            }
237        }
238    };
239}
240
241position!(pub(crate), PhysicalPositionF64, f64 => from_tauri, to_tauri, tauri::PhysicalPosition::<f64>);
242position!(pub(crate), PhysicalPositionI32, i32 => from_tauri, to_tauri, tauri::PhysicalPosition::<i32>);
243position!(pub(crate), LogicalPositionF64, f64 => from_tauri, to_tauri, tauri::LogicalPosition::<f64>);
244size!(pub(crate), PhysicalSizeU32, u32 => from_tauri, to_tauri, tauri::PhysicalSize::<u32>);
245size!(pub(crate), LogicalSizeF64, f64 => from_tauri, to_tauri, tauri::LogicalSize::<f64>);