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    /// ColorEdit: disable rendering R/G/B/A color markers.
39    pub const NO_COLOR_MARKERS: Self = Self(sys::ImGuiColorEditFlags_NoColorMarkers as u32);
40
41    /// ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
42    pub const ALPHA_BAR: Self = Self(sys::ImGuiColorEditFlags_AlphaBar as u32);
43    /// ColorEdit, ColorPicker, ColorButton: disable alpha in the preview.
44    pub const ALPHA_OPAQUE: Self = Self(sys::ImGuiColorEditFlags_AlphaOpaque as u32);
45    /// ColorEdit, ColorPicker, ColorButton: disable the checkerboard background behind transparent colors.
46    pub const ALPHA_NO_BG: Self = Self(sys::ImGuiColorEditFlags_AlphaNoBg as u32);
47    /// Compatibility alias for [`Self::ALPHA_NO_BG`].
48    pub const ALPHA_PREVIEW: Self = Self::ALPHA_NO_BG;
49    /// ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque.
50    pub const ALPHA_PREVIEW_HALF: Self = Self(sys::ImGuiColorEditFlags_AlphaPreviewHalf as u32);
51    /// (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
52    pub const HDR: Self = Self(sys::ImGuiColorEditFlags_HDR as u32);
53
54    /// Returns the underlying bits
55    pub const fn bits(self) -> u32 {
56        self.0
57    }
58
59    /// Returns true if all flags are set
60    pub const fn contains(self, other: Self) -> bool {
61        (self.0 & other.0) == other.0
62    }
63
64    /// Returns all independently composable public color flags.
65    pub const fn all() -> Self {
66        Self(
67            Self::NO_ALPHA.0
68                | Self::NO_PICKER.0
69                | Self::NO_OPTIONS.0
70                | Self::NO_SMALL_PREVIEW.0
71                | Self::NO_INPUTS.0
72                | Self::NO_TOOLTIP.0
73                | Self::NO_LABEL.0
74                | Self::NO_SIDE_PREVIEW.0
75                | Self::NO_DRAG_DROP.0
76                | Self::NO_BORDER.0
77                | Self::NO_COLOR_MARKERS.0
78                | Self::ALPHA_BAR.0
79                | Self::ALPHA_OPAQUE.0
80                | Self::ALPHA_NO_BG.0
81                | Self::ALPHA_PREVIEW_HALF.0
82                | Self::HDR.0,
83        )
84    }
85}
86
87impl Default for ColorEditFlags {
88    fn default() -> Self {
89        Self::NONE
90    }
91}
92
93/// Single display mode for color edit widgets.
94#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
95pub enum ColorDisplayMode {
96    Rgb,
97    Hsv,
98    Hex,
99}
100
101impl ColorDisplayMode {
102    const fn raw(self) -> u32 {
103        match self {
104            Self::Rgb => sys::ImGuiColorEditFlags_DisplayRGB as u32,
105            Self::Hsv => sys::ImGuiColorEditFlags_DisplayHSV as u32,
106            Self::Hex => sys::ImGuiColorEditFlags_DisplayHex as u32,
107        }
108    }
109}
110
111/// Single numeric representation for color edit widgets and defaults.
112#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
113pub enum ColorDataType {
114    Uint8,
115    Float,
116}
117
118impl ColorDataType {
119    const fn raw(self) -> u32 {
120        match self {
121            Self::Uint8 => sys::ImGuiColorEditFlags_Uint8 as u32,
122            Self::Float => sys::ImGuiColorEditFlags_Float as u32,
123        }
124    }
125}
126
127/// Single picker implementation for color picker widgets and defaults.
128#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
129pub enum ColorPickerMode {
130    HueBar,
131    HueWheel,
132}
133
134impl ColorPickerMode {
135    const fn raw(self) -> u32 {
136        match self {
137            Self::HueBar => sys::ImGuiColorEditFlags_PickerHueBar as u32,
138            Self::HueWheel => sys::ImGuiColorEditFlags_PickerHueWheel as u32,
139        }
140    }
141}
142
143/// Single input/output color space for color edit and picker widgets.
144#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
145pub enum ColorInputMode {
146    Rgb,
147    Hsv,
148}
149
150impl ColorInputMode {
151    const fn raw(self) -> u32 {
152        match self {
153            Self::Rgb => sys::ImGuiColorEditFlags_InputRGB as u32,
154            Self::Hsv => sys::ImGuiColorEditFlags_InputHSV as u32,
155        }
156    }
157}
158
159bitflags::bitflags! {
160    /// Display sub-editors visible inside `ColorPicker*()`.
161    #[repr(transparent)]
162    #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
163    pub struct ColorPickerDisplayFlags: u32 {
164        const RGB = sys::ImGuiColorEditFlags_DisplayRGB as u32;
165        const HSV = sys::ImGuiColorEditFlags_DisplayHSV as u32;
166        const HEX = sys::ImGuiColorEditFlags_DisplayHex as u32;
167    }
168}
169
170/// Options accepted by `ColorEdit3()`, `ColorEdit4()`, and
171/// `SetColorEditOptions()`.
172#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
173pub struct ColorEditOptions {
174    pub flags: ColorEditFlags,
175    pub display_mode: Option<ColorDisplayMode>,
176    pub data_type: Option<ColorDataType>,
177    pub picker_mode: Option<ColorPickerMode>,
178    pub input_mode: Option<ColorInputMode>,
179}
180
181impl ColorEditOptions {
182    pub const fn new() -> Self {
183        Self {
184            flags: ColorEditFlags::NONE,
185            display_mode: None,
186            data_type: None,
187            picker_mode: None,
188            input_mode: None,
189        }
190    }
191
192    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
193        self.flags = flags;
194        self
195    }
196
197    pub fn display_mode(mut self, mode: ColorDisplayMode) -> Self {
198        self.display_mode = Some(mode);
199        self
200    }
201
202    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
203        self.data_type = Some(data_type);
204        self
205    }
206
207    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
208        self.picker_mode = Some(mode);
209        self
210    }
211
212    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
213        self.input_mode = Some(mode);
214        self
215    }
216
217    pub fn bits(self) -> u32 {
218        self.flags.bits()
219            | self.display_mode.map_or(0, ColorDisplayMode::raw)
220            | self.data_type.map_or(0, ColorDataType::raw)
221            | self.picker_mode.map_or(0, ColorPickerMode::raw)
222            | self.input_mode.map_or(0, ColorInputMode::raw)
223    }
224
225    pub(crate) fn validate(self, caller: &str) {
226        validate_color_independent_flags(caller, self.flags);
227        validate_color_supported_bits(caller, self.bits(), color_edit_supported_mask());
228        assert_color_single_choice_mask(caller, self.bits(), color_display_mask(), "display mode");
229        assert_color_single_choice_mask(caller, self.bits(), color_data_type_mask(), "data type");
230        assert_color_single_choice_mask(caller, self.bits(), color_picker_mask(), "picker mode");
231        assert_color_single_choice_mask(caller, self.bits(), color_input_mask(), "input mode");
232    }
233}
234
235impl Default for ColorEditOptions {
236    fn default() -> Self {
237        Self::new()
238    }
239}
240
241impl From<ColorEditFlags> for ColorEditOptions {
242    fn from(flags: ColorEditFlags) -> Self {
243        Self::new().flags(flags)
244    }
245}
246
247/// Options accepted by `ColorPicker3()` and `ColorPicker4()`.
248#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
249pub struct ColorPickerOptions {
250    pub flags: ColorEditFlags,
251    pub display_flags: ColorPickerDisplayFlags,
252    pub data_type: Option<ColorDataType>,
253    pub picker_mode: Option<ColorPickerMode>,
254    pub input_mode: Option<ColorInputMode>,
255}
256
257impl ColorPickerOptions {
258    pub const fn new() -> Self {
259        Self {
260            flags: ColorEditFlags::NONE,
261            display_flags: ColorPickerDisplayFlags::empty(),
262            data_type: None,
263            picker_mode: None,
264            input_mode: None,
265        }
266    }
267
268    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
269        self.flags = flags;
270        self
271    }
272
273    pub fn display_flags(mut self, flags: ColorPickerDisplayFlags) -> Self {
274        self.display_flags = flags;
275        self
276    }
277
278    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
279        self.data_type = Some(data_type);
280        self
281    }
282
283    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
284        self.picker_mode = Some(mode);
285        self
286    }
287
288    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
289        self.input_mode = Some(mode);
290        self
291    }
292
293    pub fn bits(self) -> u32 {
294        self.flags.bits()
295            | self.display_flags.bits()
296            | self.data_type.map_or(0, ColorDataType::raw)
297            | self.picker_mode.map_or(0, ColorPickerMode::raw)
298            | self.input_mode.map_or(0, ColorInputMode::raw)
299    }
300
301    pub(crate) fn validate(self, caller: &str) {
302        validate_color_independent_flags(caller, self.flags);
303        let unsupported_display =
304            self.display_flags.bits() & !ColorPickerDisplayFlags::all().bits();
305        assert!(
306            unsupported_display == 0,
307            "{caller} received unsupported ColorPickerDisplayFlags bits: 0x{unsupported_display:X}"
308        );
309        validate_color_supported_bits(caller, self.bits(), color_picker_supported_mask());
310        assert_color_single_choice_mask(caller, self.bits(), color_data_type_mask(), "data type");
311        assert_color_single_choice_mask(caller, self.bits(), color_picker_mask(), "picker mode");
312        assert_color_single_choice_mask(caller, self.bits(), color_input_mask(), "input mode");
313    }
314}
315
316impl Default for ColorPickerOptions {
317    fn default() -> Self {
318        Self::new()
319    }
320}
321
322impl From<ColorEditFlags> for ColorPickerOptions {
323    fn from(flags: ColorEditFlags) -> Self {
324        Self::new().flags(flags)
325    }
326}
327
328/// Options accepted by `ColorButton()`.
329#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
330pub struct ColorButtonOptions {
331    pub flags: ColorEditFlags,
332    pub input_mode: Option<ColorInputMode>,
333}
334
335impl ColorButtonOptions {
336    pub const fn new() -> Self {
337        Self {
338            flags: ColorEditFlags::NONE,
339            input_mode: None,
340        }
341    }
342
343    pub fn flags(mut self, flags: ColorEditFlags) -> Self {
344        self.flags = flags;
345        self
346    }
347
348    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
349        self.input_mode = Some(mode);
350        self
351    }
352
353    pub fn bits(self) -> u32 {
354        self.flags.bits() | self.input_mode.map_or(0, ColorInputMode::raw)
355    }
356
357    pub(crate) fn validate(self, caller: &str) {
358        validate_color_independent_flags(caller, self.flags);
359        validate_color_supported_bits(caller, self.bits(), color_button_supported_mask());
360        assert_color_single_choice_mask(caller, self.bits(), color_input_mask(), "input mode");
361    }
362}
363
364impl Default for ColorButtonOptions {
365    fn default() -> Self {
366        Self::new()
367    }
368}
369
370impl From<ColorEditFlags> for ColorButtonOptions {
371    fn from(flags: ColorEditFlags) -> Self {
372        Self::new().flags(flags)
373    }
374}
375
376#[inline]
377const fn color_display_mask() -> u32 {
378    sys::ImGuiColorEditFlags_DisplayMask_ as u32
379}
380
381#[inline]
382const fn color_data_type_mask() -> u32 {
383    sys::ImGuiColorEditFlags_DataTypeMask_ as u32
384}
385
386#[inline]
387const fn color_picker_mask() -> u32 {
388    sys::ImGuiColorEditFlags_PickerMask_ as u32
389}
390
391#[inline]
392const fn color_input_mask() -> u32 {
393    sys::ImGuiColorEditFlags_InputMask_ as u32
394}
395
396#[inline]
397const fn color_choice_mask() -> u32 {
398    color_display_mask() | color_data_type_mask() | color_picker_mask() | color_input_mask()
399}
400
401#[inline]
402const fn color_edit_supported_mask() -> u32 {
403    ColorEditFlags::all().bits() | color_choice_mask()
404}
405
406#[inline]
407const fn color_picker_supported_mask() -> u32 {
408    ColorEditFlags::all().bits()
409        | color_display_mask()
410        | color_data_type_mask()
411        | color_picker_mask()
412        | color_input_mask()
413}
414
415#[inline]
416const fn color_button_supported_mask() -> u32 {
417    ColorEditFlags::all().bits() | color_input_mask()
418}
419
420fn validate_color_independent_flags(caller: &str, flags: ColorEditFlags) {
421    let unsupported = flags.bits() & !ColorEditFlags::all().bits();
422    assert!(
423        unsupported == 0,
424        "{caller} received non-independent ImGuiColorEditFlags bits: 0x{unsupported:X}"
425    );
426}
427
428fn validate_color_supported_bits(caller: &str, bits: u32, supported: u32) {
429    let unsupported = bits & !supported;
430    assert!(
431        unsupported == 0,
432        "{caller} received unsupported ImGuiColorEditFlags bits: 0x{unsupported:X}"
433    );
434}
435
436fn assert_color_single_choice_mask(caller: &str, bits: u32, mask: u32, name: &str) {
437    assert!(
438        (bits & mask).count_ones() <= 1,
439        "{caller} accepts at most one color {name}"
440    );
441}
442
443fn assert_finite_color3(caller: &str, name: &str, color: &[f32; 3]) {
444    assert!(
445        color.iter().all(|component| component.is_finite()),
446        "{caller} {name} must contain finite values"
447    );
448}
449
450fn assert_finite_color4(caller: &str, name: &str, color: &[f32; 4]) {
451    assert!(
452        color.iter().all(|component| component.is_finite()),
453        "{caller} {name} must contain finite values"
454    );
455}
456
457fn assert_non_negative_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
458    assert!(
459        value[0].is_finite() && value[1].is_finite(),
460        "{caller} {name} must contain finite values"
461    );
462    assert!(
463        value[0] >= 0.0 && value[1] >= 0.0,
464        "{caller} {name} must contain non-negative values"
465    );
466}
467
468impl std::ops::BitOr for ColorEditFlags {
469    type Output = Self;
470    fn bitor(self, rhs: Self) -> Self::Output {
471        Self(self.0 | rhs.0)
472    }
473}
474
475impl std::ops::BitOrAssign for ColorEditFlags {
476    fn bitor_assign(&mut self, rhs: Self) {
477        self.0 |= rhs.0;
478    }
479}
480
481impl std::ops::BitAnd for ColorEditFlags {
482    type Output = Self;
483    fn bitand(self, rhs: Self) -> Self::Output {
484        Self(self.0 & rhs.0)
485    }
486}
487
488impl std::ops::BitAndAssign for ColorEditFlags {
489    fn bitand_assign(&mut self, rhs: Self) {
490        self.0 &= rhs.0;
491    }
492}
493
494impl std::ops::BitXor for ColorEditFlags {
495    type Output = Self;
496    fn bitxor(self, rhs: Self) -> Self::Output {
497        Self(self.0 ^ rhs.0)
498    }
499}
500
501impl std::ops::BitXorAssign for ColorEditFlags {
502    fn bitxor_assign(&mut self, rhs: Self) {
503        self.0 ^= rhs.0;
504    }
505}
506
507impl std::ops::Not for ColorEditFlags {
508    type Output = Self;
509    fn not(self) -> Self::Output {
510        Self(!self.0)
511    }
512}
513
514/// # Color Edit Widgets
515impl Ui {
516    /// Initializes default color editing/picking options.
517    ///
518    /// This configures the defaults used by the various `Color*` widgets (unless
519    /// overridden per-call via flags). Users can still change many options via
520    /// the right-click context menu unless `_NO_OPTIONS` is passed.
521    #[doc(alias = "SetColorEditOptions")]
522    pub fn set_color_edit_options(&self, options: impl Into<ColorEditOptions>) {
523        let options = options.into();
524        options.validate("Ui::set_color_edit_options()");
525        unsafe { sys::igSetColorEditOptions(options.bits() as i32) }
526    }
527
528    /// Creates a color edit widget for 3 components (RGB)
529    #[doc(alias = "ColorEdit3")]
530    pub fn color_edit3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
531        self.color_edit3_config(label.as_ref(), color).build()
532    }
533
534    /// Creates a color edit widget for 4 components (RGBA)
535    #[doc(alias = "ColorEdit4")]
536    pub fn color_edit4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
537        self.color_edit4_config(label.as_ref(), color).build()
538    }
539
540    /// Creates a color picker widget for 3 components (RGB)
541    #[doc(alias = "ColorPicker3")]
542    pub fn color_picker3(&self, label: impl AsRef<str>, color: &mut [f32; 3]) -> bool {
543        self.color_picker3_config(label.as_ref(), color).build()
544    }
545
546    /// Creates a color picker widget for 4 components (RGBA)
547    #[doc(alias = "ColorPicker4")]
548    pub fn color_picker4(&self, label: impl AsRef<str>, color: &mut [f32; 4]) -> bool {
549        self.color_picker4_config(label.as_ref(), color).build()
550    }
551
552    /// Creates a color button widget
553    #[doc(alias = "ColorButton")]
554    pub fn color_button(&self, desc_id: impl AsRef<str>, color: [f32; 4]) -> bool {
555        self.color_button_config(desc_id.as_ref(), color).build()
556    }
557
558    /// Creates a color edit builder for 3 components
559    pub fn color_edit3_config<'ui, 'p>(
560        &'ui self,
561        label: impl Into<Cow<'ui, str>>,
562        color: &'p mut [f32; 3],
563    ) -> ColorEdit3<'ui, 'p> {
564        ColorEdit3::new(self, label, color)
565    }
566
567    /// Creates a color edit builder for 4 components
568    pub fn color_edit4_config<'ui, 'p>(
569        &'ui self,
570        label: impl Into<Cow<'ui, str>>,
571        color: &'p mut [f32; 4],
572    ) -> ColorEdit4<'ui, 'p> {
573        ColorEdit4::new(self, label, color)
574    }
575
576    /// Creates a color picker builder for 3 components
577    pub fn color_picker3_config<'ui, 'p>(
578        &'ui self,
579        label: impl Into<Cow<'ui, str>>,
580        color: &'p mut [f32; 3],
581    ) -> ColorPicker3<'ui, 'p> {
582        ColorPicker3::new(self, label, color)
583    }
584
585    /// Creates a color picker builder for 4 components
586    pub fn color_picker4_config<'ui, 'p>(
587        &'ui self,
588        label: impl Into<Cow<'ui, str>>,
589        color: &'p mut [f32; 4],
590    ) -> ColorPicker4<'ui, 'p> {
591        ColorPicker4::new(self, label, color)
592    }
593
594    /// Creates a color button builder
595    pub fn color_button_config<'ui>(
596        &'ui self,
597        desc_id: impl Into<Cow<'ui, str>>,
598        color: [f32; 4],
599    ) -> ColorButton<'ui> {
600        ColorButton::new(self, desc_id, color)
601    }
602}
603
604/// Builder for a 3-component color edit widget
605#[derive(Debug)]
606#[must_use]
607pub struct ColorEdit3<'ui, 'p> {
608    ui: &'ui Ui,
609    label: Cow<'ui, str>,
610    color: &'p mut [f32; 3],
611    flags: ColorEditOptions,
612}
613
614impl<'ui, 'p> ColorEdit3<'ui, 'p> {
615    /// Creates a new color edit builder
616    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
617        Self {
618            ui,
619            label: label.into(),
620            color,
621            flags: ColorEditOptions::new(),
622        }
623    }
624
625    /// Sets the flags for the color edit
626    pub fn flags(mut self, flags: impl Into<ColorEditOptions>) -> Self {
627        self.flags = flags.into();
628        self
629    }
630
631    /// Sets the display mode.
632    pub fn display_mode(mut self, mode: ColorDisplayMode) -> Self {
633        self.flags.display_mode = Some(mode);
634        self
635    }
636
637    /// Sets the numeric data type.
638    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
639        self.flags.data_type = Some(data_type);
640        self
641    }
642
643    /// Sets the picker mode used by the popup picker.
644    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
645        self.flags.picker_mode = Some(mode);
646        self
647    }
648
649    /// Sets the input/output color space.
650    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
651        self.flags.input_mode = Some(mode);
652        self
653    }
654
655    /// Builds the color edit widget
656    pub fn build(self) -> bool {
657        self.flags.validate("ColorEdit3::build()");
658        assert_finite_color3("ColorEdit3::build()", "color", &*self.color);
659        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
660        unsafe { sys::igColorEdit3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
661    }
662}
663
664/// Builder for a 4-component color edit widget
665#[derive(Debug)]
666#[must_use]
667pub struct ColorEdit4<'ui, 'p> {
668    ui: &'ui Ui,
669    label: Cow<'ui, str>,
670    color: &'p mut [f32; 4],
671    flags: ColorEditOptions,
672}
673
674impl<'ui, 'p> ColorEdit4<'ui, 'p> {
675    /// Creates a new color edit builder
676    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
677        Self {
678            ui,
679            label: label.into(),
680            color,
681            flags: ColorEditOptions::new(),
682        }
683    }
684
685    /// Sets the flags for the color edit
686    pub fn flags(mut self, flags: impl Into<ColorEditOptions>) -> Self {
687        self.flags = flags.into();
688        self
689    }
690
691    /// Sets the display mode.
692    pub fn display_mode(mut self, mode: ColorDisplayMode) -> Self {
693        self.flags.display_mode = Some(mode);
694        self
695    }
696
697    /// Sets the numeric data type.
698    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
699        self.flags.data_type = Some(data_type);
700        self
701    }
702
703    /// Sets the picker mode used by the popup picker.
704    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
705        self.flags.picker_mode = Some(mode);
706        self
707    }
708
709    /// Sets the input/output color space.
710    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
711        self.flags.input_mode = Some(mode);
712        self
713    }
714
715    /// Builds the color edit widget
716    pub fn build(self) -> bool {
717        self.flags.validate("ColorEdit4::build()");
718        assert_finite_color4("ColorEdit4::build()", "color", &*self.color);
719        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
720        unsafe { sys::igColorEdit4(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
721    }
722}
723
724/// Builder for a 3-component color picker widget
725#[derive(Debug)]
726#[must_use]
727pub struct ColorPicker3<'ui, 'p> {
728    ui: &'ui Ui,
729    label: Cow<'ui, str>,
730    color: &'p mut [f32; 3],
731    flags: ColorPickerOptions,
732}
733
734impl<'ui, 'p> ColorPicker3<'ui, 'p> {
735    /// Creates a new color picker builder
736    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 3]) -> Self {
737        Self {
738            ui,
739            label: label.into(),
740            color,
741            flags: ColorPickerOptions::new(),
742        }
743    }
744
745    /// Sets the flags for the color picker
746    pub fn flags(mut self, flags: impl Into<ColorPickerOptions>) -> Self {
747        self.flags = flags.into();
748        self
749    }
750
751    /// Sets the display sub-editors shown inside the picker.
752    pub fn display_flags(mut self, flags: ColorPickerDisplayFlags) -> Self {
753        self.flags.display_flags = flags;
754        self
755    }
756
757    /// Sets the numeric data type.
758    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
759        self.flags.data_type = Some(data_type);
760        self
761    }
762
763    /// Sets the picker mode.
764    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
765        self.flags.picker_mode = Some(mode);
766        self
767    }
768
769    /// Sets the input/output color space.
770    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
771        self.flags.input_mode = Some(mode);
772        self
773    }
774
775    /// Builds the color picker widget
776    pub fn build(self) -> bool {
777        self.flags.validate("ColorPicker3::build()");
778        assert_finite_color3("ColorPicker3::build()", "color", &*self.color);
779        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
780        unsafe { sys::igColorPicker3(label_ptr, self.color.as_mut_ptr(), self.flags.bits() as i32) }
781    }
782}
783
784/// Builder for a 4-component color picker widget
785#[derive(Debug)]
786#[must_use]
787pub struct ColorPicker4<'ui, 'p> {
788    ui: &'ui Ui,
789    label: Cow<'ui, str>,
790    color: &'p mut [f32; 4],
791    flags: ColorPickerOptions,
792    ref_color: Option<[f32; 4]>,
793}
794
795impl<'ui, 'p> ColorPicker4<'ui, 'p> {
796    /// Creates a new color picker builder
797    pub fn new(ui: &'ui Ui, label: impl Into<Cow<'ui, str>>, color: &'p mut [f32; 4]) -> Self {
798        Self {
799            ui,
800            label: label.into(),
801            color,
802            flags: ColorPickerOptions::new(),
803            ref_color: None,
804        }
805    }
806
807    /// Sets the flags for the color picker
808    pub fn flags(mut self, flags: impl Into<ColorPickerOptions>) -> Self {
809        self.flags = flags.into();
810        self
811    }
812
813    /// Sets the display sub-editors shown inside the picker.
814    pub fn display_flags(mut self, flags: ColorPickerDisplayFlags) -> Self {
815        self.flags.display_flags = flags;
816        self
817    }
818
819    /// Sets the numeric data type.
820    pub fn data_type(mut self, data_type: ColorDataType) -> Self {
821        self.flags.data_type = Some(data_type);
822        self
823    }
824
825    /// Sets the picker mode.
826    pub fn picker_mode(mut self, mode: ColorPickerMode) -> Self {
827        self.flags.picker_mode = Some(mode);
828        self
829    }
830
831    /// Sets the input/output color space.
832    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
833        self.flags.input_mode = Some(mode);
834        self
835    }
836
837    /// Sets the reference color for comparison
838    pub fn reference_color(mut self, ref_color: [f32; 4]) -> Self {
839        self.ref_color = Some(ref_color);
840        self
841    }
842
843    /// Builds the color picker widget
844    pub fn build(self) -> bool {
845        self.flags.validate("ColorPicker4::build()");
846        assert_finite_color4("ColorPicker4::build()", "color", &*self.color);
847        if let Some(ref_color) = &self.ref_color {
848            assert_finite_color4("ColorPicker4::build()", "reference color", ref_color);
849        }
850        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
851        let ref_color_ptr = self
852            .ref_color
853            .as_ref()
854            .map_or(std::ptr::null(), |c| c.as_ptr());
855
856        unsafe {
857            sys::igColorPicker4(
858                label_ptr,
859                self.color.as_mut_ptr(),
860                self.flags.bits() as i32,
861                ref_color_ptr,
862            )
863        }
864    }
865}
866
867/// Builder for a color button widget
868#[derive(Debug)]
869#[must_use]
870pub struct ColorButton<'ui> {
871    ui: &'ui Ui,
872    desc_id: Cow<'ui, str>,
873    color: [f32; 4],
874    flags: ColorButtonOptions,
875    size: [f32; 2],
876}
877
878impl<'ui> ColorButton<'ui> {
879    /// Creates a new color button builder
880    pub fn new(ui: &'ui Ui, desc_id: impl Into<Cow<'ui, str>>, color: [f32; 4]) -> Self {
881        Self {
882            ui,
883            desc_id: desc_id.into(),
884            color,
885            flags: ColorButtonOptions::new(),
886            size: [0.0, 0.0],
887        }
888    }
889
890    /// Sets the flags for the color button
891    pub fn flags(mut self, flags: impl Into<ColorButtonOptions>) -> Self {
892        self.flags = flags.into();
893        self
894    }
895
896    /// Sets the input color space.
897    pub fn input_mode(mut self, mode: ColorInputMode) -> Self {
898        self.flags.input_mode = Some(mode);
899        self
900    }
901
902    /// Sets the size of the color button
903    pub fn size(mut self, size: [f32; 2]) -> Self {
904        self.size = size;
905        self
906    }
907
908    /// Builds the color button widget
909    pub fn build(self) -> bool {
910        self.flags.validate("ColorButton::build()");
911        assert_finite_color4("ColorButton::build()", "color", &self.color);
912        assert_non_negative_finite_vec2("ColorButton::build()", "size", self.size);
913        let desc_id_ptr = self.ui.scratch_txt(self.desc_id.as_ref());
914        let size_vec: sys::ImVec2 = self.size.into();
915
916        unsafe {
917            sys::igColorButton(
918                desc_id_ptr,
919                sys::ImVec4 {
920                    x: self.color[0],
921                    y: self.color[1],
922                    z: self.color[2],
923                    w: self.color[3],
924                },
925                self.flags.bits() as i32,
926                size_vec,
927            )
928        }
929    }
930}