dear_imgui_rs/widget/
color.rs

1//! Color widgets
2//!
3//! Color edit/picker/button widgets and their option flags. Useful for editing
4//! RGBA values with different display/input modes.
5//!
6use crate::sys;
7use crate::ui::Ui;
8use std::borrow::Cow;
9
10/// Flags for color edit widgets
11#[repr(transparent)]
12#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
13pub struct ColorEditFlags(u32);
14
15impl ColorEditFlags {
16    /// No flags
17    pub const NONE: Self = Self(0);
18    /// ColorEdit, ColorPicker, ColorButton: ignore Alpha component (will only read 3 components from the input pointer).
19    pub const NO_ALPHA: Self = Self(sys::ImGuiColorEditFlags_NoAlpha as u32);
20    /// ColorEdit: disable picker when clicking on color square.
21    pub const NO_PICKER: Self = Self(sys::ImGuiColorEditFlags_NoPicker as u32);
22    /// ColorEdit: disable toggling options menu when right-clicking on inputs/small preview.
23    pub const NO_OPTIONS: Self = Self(sys::ImGuiColorEditFlags_NoOptions as u32);
24    /// ColorEdit, ColorPicker: disable color square preview next to the inputs. (e.g. to show only the inputs)
25    pub const NO_SMALL_PREVIEW: Self = Self(sys::ImGuiColorEditFlags_NoSmallPreview as u32);
26    /// ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview color square).
27    pub const NO_INPUTS: Self = Self(sys::ImGuiColorEditFlags_NoInputs as u32);
28    /// ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview.
29    pub const NO_TOOLTIP: Self = Self(sys::ImGuiColorEditFlags_NoTooltip as u32);
30    /// ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker).
31    pub const NO_LABEL: Self = Self(sys::ImGuiColorEditFlags_NoLabel as u32);
32    /// ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead.
33    pub const NO_SIDE_PREVIEW: Self = Self(sys::ImGuiColorEditFlags_NoSidePreview as u32);
34    /// ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source.
35    pub const NO_DRAG_DROP: Self = Self(sys::ImGuiColorEditFlags_NoDragDrop as u32);
36    /// ColorButton: disable border (which is enforced by default)
37    pub const NO_BORDER: Self = Self(sys::ImGuiColorEditFlags_NoBorder as u32);
38
39    /// ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
40    pub const ALPHA_BAR: Self = Self(sys::ImGuiColorEditFlags_AlphaBar as u32);
41    /// ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque.
42    pub const ALPHA_PREVIEW: Self = Self(sys::ImGuiColorEditFlags_AlphaNoBg as u32);
43    /// ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque.
44    pub const ALPHA_PREVIEW_HALF: Self = Self(sys::ImGuiColorEditFlags_AlphaPreviewHalf as u32);
45    /// (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
46    pub const HDR: Self = Self(sys::ImGuiColorEditFlags_HDR as u32);
47    /// ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
48    pub const DISPLAY_RGB: Self = Self(sys::ImGuiColorEditFlags_DisplayRGB as u32);
49    /// ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
50    pub const DISPLAY_HSV: Self = Self(sys::ImGuiColorEditFlags_DisplayHSV as u32);
51    /// ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
52    pub const DISPLAY_HEX: Self = Self(sys::ImGuiColorEditFlags_DisplayHex as u32);
53    /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255.
54    pub const UINT8: Self = Self(sys::ImGuiColorEditFlags_Uint8 as u32);
55    /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
56    pub const FLOAT: Self = Self(sys::ImGuiColorEditFlags_Float as u32);
57    /// ColorPicker: bar for Hue, rectangle for Sat/Value.
58    pub const PICKER_HUE_BAR: Self = Self(sys::ImGuiColorEditFlags_PickerHueBar as u32);
59    /// ColorPicker: wheel for Hue, triangle for Sat/Value.
60    pub const PICKER_HUE_WHEEL: Self = Self(sys::ImGuiColorEditFlags_PickerHueWheel as u32);
61    /// ColorEdit, ColorPicker: input and output data in RGB format.
62    pub const INPUT_RGB: Self = Self(sys::ImGuiColorEditFlags_InputRGB as u32);
63    /// ColorEdit, ColorPicker: input and output data in HSV format.
64    pub const INPUT_HSV: Self = Self(sys::ImGuiColorEditFlags_InputHSV as u32);
65
66    /// Returns the underlying bits
67    pub const fn bits(self) -> u32 {
68        self.0
69    }
70
71    /// Returns true if all flags are set
72    pub const fn contains(self, other: Self) -> bool {
73        (self.0 & other.0) == other.0
74    }
75}
76
77impl std::ops::BitOr for ColorEditFlags {
78    type Output = Self;
79    fn bitor(self, rhs: Self) -> Self::Output {
80        Self(self.0 | rhs.0)
81    }
82}
83
84impl std::ops::BitOrAssign for ColorEditFlags {
85    fn bitor_assign(&mut self, rhs: Self) {
86        self.0 |= rhs.0;
87    }
88}
89
90impl std::ops::BitAnd for ColorEditFlags {
91    type Output = Self;
92    fn bitand(self, rhs: Self) -> Self::Output {
93        Self(self.0 & rhs.0)
94    }
95}
96
97impl std::ops::BitAndAssign for ColorEditFlags {
98    fn bitand_assign(&mut self, rhs: Self) {
99        self.0 &= rhs.0;
100    }
101}
102
103impl std::ops::BitXor for ColorEditFlags {
104    type Output = Self;
105    fn bitxor(self, rhs: Self) -> Self::Output {
106        Self(self.0 ^ rhs.0)
107    }
108}
109
110impl std::ops::BitXorAssign for ColorEditFlags {
111    fn bitxor_assign(&mut self, rhs: Self) {
112        self.0 ^= rhs.0;
113    }
114}
115
116impl std::ops::Not for ColorEditFlags {
117    type Output = Self;
118    fn not(self) -> Self::Output {
119        Self(!self.0)
120    }
121}
122
123/// # Color Edit Widgets
124impl Ui {
125    /// Creates a color edit widget for 3 components (RGB)
126    #[doc(alias = "ColorEdit3")]
127    pub fn color_edit3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
128        self.color_edit3_config(label.as_ref(), color).build()
129    }
130
131    /// Creates a color edit widget for 4 components (RGBA)
132    #[doc(alias = "ColorEdit4")]
133    pub fn color_edit4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
134        self.color_edit4_config(label.as_ref(), color).build()
135    }
136
137    /// Creates a color picker widget for 3 components (RGB)
138    #[doc(alias = "ColorPicker3")]
139    pub fn color_picker3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
140        self.color_picker3_config(label.as_ref(), color).build()
141    }
142
143    /// Creates a color picker widget for 4 components (RGBA)
144    #[doc(alias = "ColorPicker4")]
145    pub fn color_picker4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
146        self.color_picker4_config(label.as_ref(), color).build()
147    }
148
149    /// Creates a color button widget
150    #[doc(alias = "ColorButton")]
151    pub fn color_button(&self, desc_id: impl AsRef<str>, color: [f32; 4]) -> bool {
152        self.color_button_config(desc_id.as_ref(), color).build()
153    }
154
155    /// Creates a color edit builder for 3 components
156    pub fn color_edit3_config<'ui, 'p>(
157        &'ui self,
158        label: impl Into<Cow<'ui, str>>,
159        color: &'p mut [f32; 3],
160    ) -> ColorEdit3<'ui, 'p> {
161        ColorEdit3::new(self, label, color)
162    }
163
164    /// Creates a color edit builder for 4 components
165    pub fn color_edit4_config<'ui, 'p>(
166        &'ui self,
167        label: impl Into<Cow<'ui, str>>,
168        color: &'p mut [f32; 4],
169    ) -> ColorEdit4<'ui, 'p> {
170        ColorEdit4::new(self, label, color)
171    }
172
173    /// Creates a color picker builder for 3 components
174    pub fn color_picker3_config<'ui, 'p>(
175        &'ui self,
176        label: impl Into<Cow<'ui, str>>,
177        color: &'p mut [f32; 3],
178    ) -> ColorPicker3<'ui, 'p> {
179        ColorPicker3::new(self, label, color)
180    }
181
182    /// Creates a color picker builder for 4 components
183    pub fn color_picker4_config<'ui, 'p>(
184        &'ui self,
185        label: impl Into<Cow<'ui, str>>,
186        color: &'p mut [f32; 4],
187    ) -> ColorPicker4<'ui, 'p> {
188        ColorPicker4::new(self, label, color)
189    }
190
191    /// Creates a color button builder
192    pub fn color_button_config<'ui>(
193        &'ui self,
194        desc_id: impl Into<Cow<'ui, str>>,
195        color: [f32; 4],
196    ) -> ColorButton<'ui> {
197        ColorButton::new(self, desc_id, color)
198    }
199}
200
201/// Builder for a 3-component color edit widget
202#[derive(Debug)]
203#[must_use]
204pub struct ColorEdit3<'ui, 'p> {
205    ui: &'ui Ui,
206    label: Cow<'ui, str>,
207    color: &'p mut [f32; 3],
208    flags: ColorEditFlags,
209}
210
211impl<'ui, 'p> ColorEdit3<'ui, 'p> {
212    /// Creates a new color edit builder
213    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
214        Self {
215            ui,
216            label: label.into(),
217            color,
218            flags: ColorEditFlags::NONE,
219        }
220    }
221
222    /// Sets the flags for the color edit
223    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
224        self.flags = flags;
225        self
226    }
227
228    /// Builds the color edit widget
229    pub fn build(self) -> bool {
230        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
231        unsafe { sys::igColorEdit3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
232    }
233}
234
235/// Builder for a 4-component color edit widget
236#[derive(Debug)]
237#[must_use]
238pub struct ColorEdit4<'ui, 'p> {
239    ui: &'ui Ui,
240    label: Cow<'ui, str>,
241    color: &'p mut [f32; 4],
242    flags: ColorEditFlags,
243}
244
245impl<'ui, 'p> ColorEdit4<'ui, 'p> {
246    /// Creates a new color edit builder
247    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
248        Self {
249            ui,
250            label: label.into(),
251            color,
252            flags: ColorEditFlags::NONE,
253        }
254    }
255
256    /// Sets the flags for the color edit
257    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
258        self.flags = flags;
259        self
260    }
261
262    /// Builds the color edit widget
263    pub fn build(self) -> bool {
264        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
265        unsafe { sys::igColorEdit4(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
266    }
267}
268
269/// Builder for a 3-component color picker widget
270#[derive(Debug)]
271#[must_use]
272pub struct ColorPicker3<'ui, 'p> {
273    ui: &'ui Ui,
274    label: Cow<'ui, str>,
275    color: &'p mut [f32; 3],
276    flags: ColorEditFlags,
277}
278
279impl<'ui, 'p> ColorPicker3<'ui, 'p> {
280    /// Creates a new color picker builder
281    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
282        Self {
283            ui,
284            label: label.into(),
285            color,
286            flags: ColorEditFlags::NONE,
287        }
288    }
289
290    /// Sets the flags for the color picker
291    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
292        self.flags = flags;
293        self
294    }
295
296    /// Builds the color picker widget
297    pub fn build(self) -> bool {
298        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
299        unsafe { sys::igColorPicker3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
300    }
301}
302
303/// Builder for a 4-component color picker widget
304#[derive(Debug)]
305#[must_use]
306pub struct ColorPicker4<'ui, 'p> {
307    ui: &'ui Ui,
308    label: Cow<'ui, str>,
309    color: &'p mut [f32; 4],
310    flags: ColorEditFlags,
311    ref_color: Option<[f32; 4]>,
312}
313
314impl<'ui, 'p> ColorPicker4<'ui, 'p> {
315    /// Creates a new color picker builder
316    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
317        Self {
318            ui,
319            label: label.into(),
320            color,
321            flags: ColorEditFlags::NONE,
322            ref_color: None,
323        }
324    }
325
326    /// Sets the flags for the color picker
327    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
328        self.flags = flags;
329        self
330    }
331
332    /// Sets the reference color for comparison
333    pub fn reference_color(mut self, ref_color: [f32; 4]) -> Self {
334        self.ref_color = Some(ref_color);
335        self
336    }
337
338    /// Builds the color picker widget
339    pub fn build(self) -> bool {
340        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
341        let ref_color_ptr = self
342            .ref_color
343            .as_ref()
344            .map_or(std::ptr::null(), |c| c.as_ptr());
345
346        unsafe {
347            sys::igColorPicker4(
348                label_ptr,
349                self.color.as_mut_ptr(),
350                self.flags.bits() as i32,
351                ref_color_ptr,
352            )
353        }
354    }
355}
356
357/// Builder for a color button widget
358#[derive(Debug)]
359#[must_use]
360pub struct ColorButton<'ui> {
361    ui: &'ui Ui,
362    desc_id: Cow<'ui, str>,
363    color: [f32; 4],
364    flags: ColorEditFlags,
365    size: [f32; 2],
366}
367
368impl<'ui> ColorButton<'ui> {
369    /// Creates a new color button builder
370    pub fn new(ui: &'ui Ui, desc_id: impl Into<Cow<'ui, str>>, color: [f32; 4]) -> Self {
371        Self {
372            ui,
373            desc_id: desc_id.into(),
374            color,
375            flags: ColorEditFlags::NONE,
376            size: [0.0, 0.0],
377        }
378    }
379
380    /// Sets the flags for the color button
381    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
382        self.flags = flags;
383        self
384    }
385
386    /// Sets the size of the color button
387    pub fn size(mut self, size: [f32; 2]) -> Self {
388        self.size = size;
389        self
390    }
391
392    /// Builds the color button widget
393    pub fn build(self) -> bool {
394        let desc_id_ptr = self.ui.scratch_txt(self.desc_id.as_ref());
395        let size_vec: sys::ImVec2 = self.size.into();
396
397        unsafe {
398            sys::igColorButton(
399                desc_id_ptr,
400                sys::ImVec4 {
401                    x: self.color[0],
402                    y: self.color[1],
403                    z: self.color[2],
404                    w: self.color[3],
405                },
406                self.flags.bits() as i32,
407                size_vec,
408            )
409        }
410    }
411}