imgui/widget/
image.rs

1use std::os::raw::c_void;
2
3use crate::math::MintVec2;
4use crate::math::MintVec4;
5use crate::render::renderer::TextureId;
6use crate::sys;
7use crate::Ui;
8
9/// Builder for an image widget
10#[derive(Copy, Clone, Debug)]
11#[must_use]
12pub struct Image {
13    texture_id: TextureId,
14    size: [f32; 2],
15    uv0: [f32; 2],
16    uv1: [f32; 2],
17    tint_col: [f32; 4],
18    border_col: [f32; 4],
19}
20
21impl Image {
22    /// Creates a new image builder with the given texture and size
23    #[doc(alias = "Image")]
24    pub fn new(texture_id: TextureId, size: impl Into<MintVec2>) -> Image {
25        Image {
26            texture_id,
27            size: size.into().into(),
28            uv0: [0.0, 0.0],
29            uv1: [1.0, 1.0],
30            tint_col: [1.0, 1.0, 1.0, 1.0],
31            border_col: [0.0, 0.0, 0.0, 0.0],
32        }
33    }
34    /// Sets the image size
35    #[deprecated(note = "just set the size in the `new` constructor.")]
36    pub fn size(mut self, size: impl Into<MintVec2>) -> Self {
37        self.size = size.into().into();
38        self
39    }
40    /// Sets uv0 (default `[0.0, 0.0]`)
41    pub fn uv0(mut self, uv0: impl Into<MintVec2>) -> Self {
42        self.uv0 = uv0.into().into();
43        self
44    }
45    /// Sets uv1 (default `[1.0, 1.0]`)
46    pub fn uv1(mut self, uv1: impl Into<MintVec2>) -> Self {
47        self.uv1 = uv1.into().into();
48        self
49    }
50    /// Sets the tint color (default: no tint color)
51    pub fn tint_col(mut self, tint_col: impl Into<MintVec4>) -> Self {
52        self.tint_col = tint_col.into().into();
53        self
54    }
55    /// Sets the border color (default: no border)
56    pub fn border_col(mut self, border_col: impl Into<MintVec4>) -> Self {
57        self.border_col = border_col.into().into();
58        self
59    }
60    /// Builds the image
61    pub fn build(self, _: &Ui) {
62        unsafe {
63            sys::igImage(
64                self.texture_id.id() as *mut c_void,
65                self.size.into(),
66                self.uv0.into(),
67                self.uv1.into(),
68                self.tint_col.into(),
69                self.border_col.into(),
70            );
71        }
72    }
73}
74
75/// Builder for an image button widget
76#[derive(Copy, Clone, Debug)]
77#[must_use]
78pub struct ImageButton<'ui, StrId> {
79    str_id: StrId,
80    texture_id: TextureId,
81    size: [f32; 2],
82    uv0: [f32; 2],
83    uv1: [f32; 2],
84    bg_col: [f32; 4],
85    tint_col: [f32; 4],
86    ui: &'ui Ui,
87}
88
89#[derive(Copy, Clone, Debug)]
90#[must_use]
91pub struct ImageButtonDeprecated {
92    texture_id: TextureId,
93    size: [f32; 2],
94    uv0: [f32; 2],
95    uv1: [f32; 2],
96    frame_padding: i32,
97    bg_col: [f32; 4],
98    tint_col: [f32; 4],
99}
100
101impl ImageButton<'static, ()> {
102    /// Creates a new image button builder with the given texture and size
103    #[deprecated(since = "0.10.0", note = "Use `ui.image_button_config(...)` instead")]
104    #[allow(clippy::new_ret_no_self)]
105    pub fn new(texture_id: TextureId, size: impl Into<MintVec2>) -> ImageButtonDeprecated {
106        ImageButtonDeprecated {
107            texture_id,
108            size: size.into().into(),
109            uv0: [0.0, 0.0],
110            uv1: [1.0, 1.0],
111            frame_padding: -1,
112            bg_col: [0.0, 0.0, 0.0, 0.0],
113            tint_col: [1.0, 1.0, 1.0, 1.0],
114        }
115    }
116}
117
118impl<'ui, StrId: AsRef<str>> ImageButton<'ui, StrId> {
119    /// Creates a new image button builder with the given texture and size
120    #[deprecated(since = "0.10.0", note = "Use `ui.image_button_config(...)` instead")]
121    pub fn new_with_id(
122        ui: &'ui Ui,
123        str_id: StrId,
124        texture_id: TextureId,
125        size: impl Into<MintVec2>,
126    ) -> Self {
127        Self {
128            str_id,
129            texture_id,
130            size: size.into().into(),
131            uv0: [0.0, 0.0],
132            uv1: [1.0, 1.0],
133            bg_col: [0.0, 0.0, 0.0, 0.0],
134            tint_col: [1.0, 1.0, 1.0, 1.0],
135            ui,
136        }
137    }
138
139    /// Sets the image button size
140    #[deprecated(note = "just set the size in the `new` constructor.")]
141    pub fn size(mut self, size: impl Into<MintVec2>) -> Self {
142        self.size = size.into().into();
143        self
144    }
145    /// Sets uv0 (default `[0.0, 0.0]`)
146    pub fn uv0(mut self, uv0: impl Into<MintVec2>) -> Self {
147        self.uv0 = uv0.into().into();
148        self
149    }
150    /// Sets uv1 (default `[1.0, 1.0]`)
151    pub fn uv1(mut self, uv1: impl Into<MintVec2>) -> Self {
152        self.uv1 = uv1.into().into();
153        self
154    }
155    /// Sets the background color (default: no background color)
156    pub fn background_col(mut self, bg_col: impl Into<MintVec4>) -> Self {
157        self.bg_col = bg_col.into().into();
158        self
159    }
160    /// Sets the tint color (default: no tint color)
161    pub fn tint_col(mut self, tint_col: impl Into<MintVec4>) -> Self {
162        self.tint_col = tint_col.into().into();
163        self
164    }
165    /// Builds the image button
166    pub fn build(self) -> bool {
167        unsafe {
168            sys::igImageButton(
169                self.ui.scratch_txt(self.str_id),
170                self.texture_id.id() as *mut c_void,
171                self.size.into(),
172                self.uv0.into(),
173                self.uv1.into(),
174                self.bg_col.into(),
175                self.tint_col.into(),
176            )
177        }
178    }
179}
180
181impl ImageButtonDeprecated {
182    /// Sets the image button size
183    #[deprecated(note = "just set the size in the `new` constructor.")]
184    pub fn size(mut self, size: impl Into<MintVec2>) -> Self {
185        self.size = size.into().into();
186        self
187    }
188    /// Sets uv0 (default `[0.0, 0.0]`)
189    pub fn uv0(mut self, uv0: impl Into<MintVec2>) -> Self {
190        self.uv0 = uv0.into().into();
191        self
192    }
193    /// Sets uv1 (default `[1.0, 1.0]`)
194    pub fn uv1(mut self, uv1: impl Into<MintVec2>) -> Self {
195        self.uv1 = uv1.into().into();
196        self
197    }
198    /// Sets the background color (default: no background color)
199    pub fn background_col(mut self, bg_col: impl Into<MintVec4>) -> Self {
200        self.bg_col = bg_col.into().into();
201        self
202    }
203    /// Sets the tint color (default: no tint color)
204    pub fn tint_col(mut self, tint_col: impl Into<MintVec4>) -> Self {
205        self.tint_col = tint_col.into().into();
206        self
207    }
208    /// Sets the frame padding (default: uses frame padding from style).
209    ///
210    /// - `< 0`: uses frame padding from style (default)
211    /// - `= 0`: no framing
212    /// - `> 0`: set framing size
213    pub fn frame_padding(mut self, frame_padding: i32) -> Self {
214        self.frame_padding = frame_padding;
215        self
216    }
217    /// Builds the image button
218    pub fn build(self, _: &Ui) -> bool {
219        unsafe {
220            sys::igPushID_Ptr(self.texture_id.id() as *const _);
221
222            if self.frame_padding >= 0 {
223                sys::igPushStyleVar_Vec2(
224                    sys::ImGuiStyleVar_FramePadding as i32,
225                    [self.frame_padding as f32, self.frame_padding as f32].into(),
226                );
227            }
228
229            let res = sys::igImageButton(
230                b"#image".as_ptr().cast(),
231                self.texture_id.id() as *mut c_void,
232                self.size.into(),
233                self.uv0.into(),
234                self.uv1.into(),
235                self.bg_col.into(),
236                self.tint_col.into(),
237            );
238
239            if self.frame_padding >= 0 {
240                sys::igPopStyleVar(1);
241            }
242
243            sys::igPopID();
244
245            res
246        }
247    }
248}
249
250impl Ui {
251    pub fn image_button(
252        &self,
253        str_id: impl AsRef<str>,
254        texture_id: TextureId,
255        size: impl Into<MintVec2>,
256    ) -> bool {
257        ImageButton {
258            str_id,
259            texture_id,
260            size: size.into().into(),
261            uv0: [0.0, 0.0],
262            uv1: [1.0, 1.0],
263            bg_col: [0.0, 0.0, 0.0, 0.0],
264            tint_col: [1.0, 1.0, 1.0, 1.0],
265            ui: self,
266        }
267        .build()
268    }
269
270    pub fn image_button_config<IdStr: AsRef<str>>(
271        &self,
272        str_id: IdStr,
273        texture_id: TextureId,
274        size: impl Into<MintVec2>,
275    ) -> ImageButton<'_, IdStr> {
276        ImageButton {
277            str_id,
278            texture_id,
279            size: size.into().into(),
280            uv0: [0.0, 0.0],
281            uv1: [1.0, 1.0],
282            bg_col: [0.0, 0.0, 0.0, 0.0],
283            tint_col: [1.0, 1.0, 1.0, 1.0],
284            ui: self,
285        }
286    }
287}