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