Skip to main content

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    /// Initializes default color editing/picking options.
126    ///
127    /// This configures the defaults used by the various `Color*` widgets (unless
128    /// overridden per-call via flags). Users can still change many options via
129    /// the right-click context menu unless `_NO_OPTIONS` is passed.
130    #[doc(alias = "SetColorEditOptions")]
131    pub fn set_color_edit_options(&self, flags: ColorEditFlags) {
132        unsafe { sys::igSetColorEditOptions(flags.bits() as i32) }
133    }
134
135    /// Creates a color edit widget for 3 components (RGB)
136    #[doc(alias = "ColorEdit3")]
137    pub fn color_edit3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
138        self.color_edit3_config(label.as_ref(), color).build()
139    }
140
141    /// Creates a color edit widget for 4 components (RGBA)
142    #[doc(alias = "ColorEdit4")]
143    pub fn color_edit4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
144        self.color_edit4_config(label.as_ref(), color).build()
145    }
146
147    /// Creates a color picker widget for 3 components (RGB)
148    #[doc(alias = "ColorPicker3")]
149    pub fn color_picker3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
150        self.color_picker3_config(label.as_ref(), color).build()
151    }
152
153    /// Creates a color picker widget for 4 components (RGBA)
154    #[doc(alias = "ColorPicker4")]
155    pub fn color_picker4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
156        self.color_picker4_config(label.as_ref(), color).build()
157    }
158
159    /// Creates a color button widget
160    #[doc(alias = "ColorButton")]
161    pub fn color_button(&self, desc_id: impl AsRef<str>, color: [f32; 4]) -> bool {
162        self.color_button_config(desc_id.as_ref(), color).build()
163    }
164
165    /// Creates a color edit builder for 3 components
166    pub fn color_edit3_config<'ui, 'p>(
167        &'ui self,
168        label: impl Into<Cow<'ui, str>>,
169        color: &'p mut [f32; 3],
170    ) -> ColorEdit3<'ui, 'p> {
171        ColorEdit3::new(self, label, color)
172    }
173
174    /// Creates a color edit builder for 4 components
175    pub fn color_edit4_config<'ui, 'p>(
176        &'ui self,
177        label: impl Into<Cow<'ui, str>>,
178        color: &'p mut [f32; 4],
179    ) -> ColorEdit4<'ui, 'p> {
180        ColorEdit4::new(self, label, color)
181    }
182
183    /// Creates a color picker builder for 3 components
184    pub fn color_picker3_config<'ui, 'p>(
185        &'ui self,
186        label: impl Into<Cow<'ui, str>>,
187        color: &'p mut [f32; 3],
188    ) -> ColorPicker3<'ui, 'p> {
189        ColorPicker3::new(self, label, color)
190    }
191
192    /// Creates a color picker builder for 4 components
193    pub fn color_picker4_config<'ui, 'p>(
194        &'ui self,
195        label: impl Into<Cow<'ui, str>>,
196        color: &'p mut [f32; 4],
197    ) -> ColorPicker4<'ui, 'p> {
198        ColorPicker4::new(self, label, color)
199    }
200
201    /// Creates a color button builder
202    pub fn color_button_config<'ui>(
203        &'ui self,
204        desc_id: impl Into<Cow<'ui, str>>,
205        color: [f32; 4],
206    ) -> ColorButton<'ui> {
207        ColorButton::new(self, desc_id, color)
208    }
209}
210
211/// Builder for a 3-component color edit widget
212#[derive(Debug)]
213#[must_use]
214pub struct ColorEdit3<'ui, 'p> {
215    ui: &'ui Ui,
216    label: Cow<'ui, str>,
217    color: &'p mut [f32; 3],
218    flags: ColorEditFlags,
219}
220
221impl<'ui, 'p> ColorEdit3<'ui, 'p> {
222    /// Creates a new color edit builder
223    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
224        Self {
225            ui,
226            label: label.into(),
227            color,
228            flags: ColorEditFlags::NONE,
229        }
230    }
231
232    /// Sets the flags for the color edit
233    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
234        self.flags = flags;
235        self
236    }
237
238    /// Builds the color edit widget
239    pub fn build(self) -> bool {
240        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
241        unsafe { sys::igColorEdit3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
242    }
243}
244
245/// Builder for a 4-component color edit widget
246#[derive(Debug)]
247#[must_use]
248pub struct ColorEdit4<'ui, 'p> {
249    ui: &'ui Ui,
250    label: Cow<'ui, str>,
251    color: &'p mut [f32; 4],
252    flags: ColorEditFlags,
253}
254
255impl<'ui, 'p> ColorEdit4<'ui, 'p> {
256    /// Creates a new color edit builder
257    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
258        Self {
259            ui,
260            label: label.into(),
261            color,
262            flags: ColorEditFlags::NONE,
263        }
264    }
265
266    /// Sets the flags for the color edit
267    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
268        self.flags = flags;
269        self
270    }
271
272    /// Builds the color edit widget
273    pub fn build(self) -> bool {
274        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
275        unsafe { sys::igColorEdit4(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
276    }
277}
278
279/// Builder for a 3-component color picker widget
280#[derive(Debug)]
281#[must_use]
282pub struct ColorPicker3<'ui, 'p> {
283    ui: &'ui Ui,
284    label: Cow<'ui, str>,
285    color: &'p mut [f32; 3],
286    flags: ColorEditFlags,
287}
288
289impl<'ui, 'p> ColorPicker3<'ui, 'p> {
290    /// Creates a new color picker builder
291    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
292        Self {
293            ui,
294            label: label.into(),
295            color,
296            flags: ColorEditFlags::NONE,
297        }
298    }
299
300    /// Sets the flags for the color picker
301    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
302        self.flags = flags;
303        self
304    }
305
306    /// Builds the color picker widget
307    pub fn build(self) -> bool {
308        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
309        unsafe { sys::igColorPicker3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
310    }
311}
312
313/// Builder for a 4-component color picker widget
314#[derive(Debug)]
315#[must_use]
316pub struct ColorPicker4<'ui, 'p> {
317    ui: &'ui Ui,
318    label: Cow<'ui, str>,
319    color: &'p mut [f32; 4],
320    flags: ColorEditFlags,
321    ref_color: Option<[f32; 4]>,
322}
323
324impl<'ui, 'p> ColorPicker4<'ui, 'p> {
325    /// Creates a new color picker builder
326    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
327        Self {
328            ui,
329            label: label.into(),
330            color,
331            flags: ColorEditFlags::NONE,
332            ref_color: None,
333        }
334    }
335
336    /// Sets the flags for the color picker
337    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
338        self.flags = flags;
339        self
340    }
341
342    /// Sets the reference color for comparison
343    pub fn reference_color(mut self, ref_color: [f32; 4]) -> Self {
344        self.ref_color = Some(ref_color);
345        self
346    }
347
348    /// Builds the color picker widget
349    pub fn build(self) -> bool {
350        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
351        let ref_color_ptr = self
352            .ref_color
353            .as_ref()
354            .map_or(std::ptr::null(), |c| c.as_ptr());
355
356        unsafe {
357            sys::igColorPicker4(
358                label_ptr,
359                self.color.as_mut_ptr(),
360                self.flags.bits() as i32,
361                ref_color_ptr,
362            )
363        }
364    }
365}
366
367/// Builder for a color button widget
368#[derive(Debug)]
369#[must_use]
370pub struct ColorButton<'ui> {
371    ui: &'ui Ui,
372    desc_id: Cow<'ui, str>,
373    color: [f32; 4],
374    flags: ColorEditFlags,
375    size: [f32; 2],
376}
377
378impl<'ui> ColorButton<'ui> {
379    /// Creates a new color button builder
380    pub fn new(ui: &'ui Ui, desc_id: impl Into<Cow<'ui, str>>, color: [f32; 4]) -> Self {
381        Self {
382            ui,
383            desc_id: desc_id.into(),
384            color,
385            flags: ColorEditFlags::NONE,
386            size: [0.0, 0.0],
387        }
388    }
389
390    /// Sets the flags for the color button
391    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
392        self.flags = flags;
393        self
394    }
395
396    /// Sets the size of the color button
397    pub fn size(mut self, size: [f32; 2]) -> Self {
398        self.size = size;
399        self
400    }
401
402    /// Builds the color button widget
403    pub fn build(self) -> bool {
404        let desc_id_ptr = self.ui.scratch_txt(self.desc_id.as_ref());
405        let size_vec: sys::ImVec2 = self.size.into();
406
407        unsafe {
408            sys::igColorButton(
409                desc_id_ptr,
410                sys::ImVec4 {
411                    x: self.color[0],
412                    y: self.color[1],
413                    z: self.color[2],
414                    w: self.color[3],
415                },
416                self.flags.bits() as i32,
417                size_vec,
418            )
419        }
420    }
421}