From 11b693271432ae795902c9e844bafcf5311d5342 Mon Sep 17 00:00:00 2001 From: Joonas Javanainen Date: Fri, 12 Jul 2019 20:03:17 +0300 Subject: [PATCH] Pull new color editor/picker API from 0.1-dev --- imgui-examples/examples/color_button.rs | 283 ++++----- imgui-examples/examples/test_window_impl.rs | 48 +- src/color_editors.rs | 426 -------------- src/legacy.rs | 81 +-- src/lib.rs | 38 +- src/widget/color_editors.rs | 614 ++++++++++++++++++++ src/widget/mod.rs | 1 + 7 files changed, 809 insertions(+), 682 deletions(-) delete mode 100644 src/color_editors.rs create mode 100644 src/widget/color_editors.rs diff --git a/imgui-examples/examples/color_button.rs b/imgui-examples/examples/color_button.rs index 1e7388c..a6fb836 100644 --- a/imgui-examples/examples/color_button.rs +++ b/imgui-examples/examples/color_button.rs @@ -2,8 +2,150 @@ use imgui::*; mod support; +fn main() { + let mut state = State::default(); + let system = support::init(file!()); + system.main_loop(|run, ui| { + example_selector(run, ui, &mut state); + match state.example { + 1 => example_1(ui, &mut state), + 2 => example_2(ui), + 3 => example_3(ui), + _ => (), + } + }); +} + +fn example_selector(run: &mut bool, ui: &mut Ui, state: &mut State) { + let w = Window::new(im_str!("Color button examples")) + .opened(run) + .position([20.0, 20.0], Condition::Appearing) + .size([700.0, 100.0], Condition::Appearing) + .resizable(false); + w.build(ui, || { + let ex1 = ui.radio_button(im_str!("Example 1: Basics"), &mut state.example, 1); + let ex2 = ui.radio_button(im_str!("Example 2: Alpha component"), &mut state.example, 2); + let ex3 = ui.radio_button(im_str!("Example 3: Input format"), &mut state.example, 3); + if ex1 || ex2 || ex3 { + state.reset(); + } + }); +} + +fn example_1(ui: &Ui, state: &mut State) { + let w = Window::new(im_str!("Example 1: Basics")) + .size([700.0, 300.0], Condition::Appearing) + .position([20.0, 140.0], Condition::Appearing); + w.build(ui, || { + ui.text_wrapped(im_str!( + "Color button is a widget that displays a color value as a clickable rectangle. \ + It also supports a tooltip with detailed information about the color value. \ + Try hovering over and clicking these buttons!" + )); + ui.text(state.notify_text); + + ui.text("This button is black:"); + if ColorButton::new(im_str!("Black color"), [0.0, 0.0, 0.0, 1.0]).build(ui) { + state.notify_text = "*** Black button was clicked"; + } + + ui.text("This button is red:"); + if ColorButton::new(im_str!("Red color"), [1.0, 0.0, 0.0, 1.0]).build(ui) { + state.notify_text = "*** Red button was clicked"; + } + + ui.text("This button is BIG because it has a custom size:"); + if ColorButton::new(im_str!("Green color"), [0.0, 1.0, 0.0, 1.0]) + .size([100.0, 50.0]) + .build(ui) + { + state.notify_text = "*** BIG button was clicked"; + } + + ui.text("This button doesn't use the tooltip at all:"); + if ColorButton::new(im_str!("No tooltip"), [0.0, 0.0, 1.0, 1.0]) + .tooltip(false) + .build(ui) + { + state.notify_text = "*** No tooltip button was clicked"; + } + }); +} + +fn example_2(ui: &Ui) { + let w = Window::new(im_str!("Example 2: Alpha component")) + .size([700.0, 320.0], Condition::Appearing) + .position([20.0, 140.0], Condition::Appearing); + w.build(ui, || { + ui.text_wrapped(im_str!( + "The displayed color is passed to the button as four float values between \ + 0.0 - 1.0 (RGBA). If you don't care about the alpha component, it can be \ + disabled and it won't show up in the tooltip" + )); + + ui.text("This button ignores the alpha component:"); + ColorButton::new(im_str!("Red color"), [1.0, 0.0, 0.0, 0.5]) + .alpha(false) + .build(ui); + + ui.spacing(); + ui.spacing(); + ui.spacing(); + ui.text_wrapped(im_str!( + "If you *do* care about the alpha component, you can choose how it's \ + displayed in the button and the tooltip" + )); + + ui.separator(); + ui.text_wrapped(im_str!( + "ColorPreview::Opaque (default) doesn't show the alpha component at all" + )); + ColorButton::new(im_str!("Red + ColorPreview::Opaque"), [1.0, 0.0, 0.0, 0.5]) + .preview(ColorPreview::Opaque) + .build(ui); + + ui.separator(); + ui.text_wrapped(im_str!( + "ColorPreview::HalfAlpha divides the color area into two halves and uses a \ + checkerboard pattern in one half to illustrate the alpha component" + )); + ColorButton::new( + im_str!("Red + ColorPreview::HalfAlpha"), + [1.0, 0.0, 0.0, 0.5], + ) + .preview(ColorPreview::HalfAlpha) + .build(ui); + + ui.separator(); + ui.text_wrapped(im_str!( + "ColorPreview::Alpha uses a checkerboard pattern in the entire color area to \ + illustrate the alpha component" + )); + ColorButton::new(im_str!("Red + ColorPreview::Alpha"), [1.0, 0.0, 0.0, 0.5]) + .preview(ColorPreview::Alpha) + .build(ui); + }); +} + +fn example_3(ui: &Ui) { + let w = Window::new(im_str!("Example 3: Input format")) + .size([700.0, 320.0], Condition::Appearing) + .position([20.0, 140.0], Condition::Appearing); + w.build(ui, || { + ui.text("This button interprets the input value [1.0, 0.0, 0.0, 1.0] as RGB(A) (default):"); + ColorButton::new(im_str!("RGBA red"), [1.0, 0.0, 0.0, 1.0]).build(ui); + + ui.separator(); + ui.text("This button interprets the input value [1.0, 0.0, 0.0, 1.0] as HSV(A):"); + ColorButton::new(im_str!("HSVA black"), [1.0, 0.0, 0.0, 1.0]) + .input_mode(ColorEditInputMode::HSV) + .build(ui); + }); +} + +#[derive(Default)] struct State { - example: i32, + example: u32, notify_text: &'static str, } @@ -12,142 +154,3 @@ impl State { self.notify_text = ""; } } - -impl Default for State { - fn default() -> State { - State { - example: 0, - notify_text: "", - } - } -} - -fn main() { - let system = support::init(file!()); - let mut state = State::default(); - system.main_loop(|_, ui| { - example_selector(&mut state, ui); - match state.example { - 1 => example_1(&mut state, ui), - 2 => example_2(ui), - _ => (), - } - }); -} - -fn example_selector(state: &mut State, ui: &Ui) { - Window::new(im_str!("Color button examples")) - .position([20.0, 20.0], Condition::Appearing) - .size([700.0, 80.0], Condition::Appearing) - .resizable(false) - .build(ui, || { - let ex1 = ui.radio_button(im_str!("Example 1: Basics"), &mut state.example, 1); - let ex2 = ui.radio_button(im_str!("Example 2: Alpha component"), &mut state.example, 2); - if ex1 || ex2 { - state.reset(); - } - }); -} - -fn example_1(state: &mut State, ui: &Ui) { - Window::new(im_str!("Example 1: Basics")) - .size([700.0, 300.0], Condition::Appearing) - .position([20.0, 120.0], Condition::Appearing) - .build(ui, || { - ui.text_wrapped(im_str!( - "Color button is a widget that displays a color value as a clickable rectangle. \ - It also supports a tooltip with detailed information about the color value. \ - Try hovering over and clicking these buttons!" - )); - ui.text(state.notify_text); - - ui.text("This button is black:"); - if ui - .color_button(im_str!("Black color"), [0.0, 0.0, 0.0, 1.0]) - .build() - { - state.notify_text = "*** Black button was clicked"; - } - - ui.text("This button is red:"); - if ui - .color_button(im_str!("Red color"), [1.0, 0.0, 0.0, 1.0]) - .build() - { - state.notify_text = "*** Red button was clicked"; - } - - ui.text("This button is BIG because it has a custom size:"); - if ui - .color_button(im_str!("Green color"), [0.0, 1.0, 0.0, 1.0]) - .size([100.0, 50.0]) - .build() - { - state.notify_text = "*** BIG button was clicked"; - } - - ui.text("This button doesn't use the tooltip at all:"); - if ui - .color_button(im_str!("No tooltip"), [0.0, 0.0, 1.0, 1.0]) - .tooltip(false) - .build() - { - state.notify_text = "*** No tooltip button was clicked"; - } - }); -} - -fn example_2(ui: &Ui) { - Window::new(im_str!("Example 2: Alpha component")) - .size([700.0, 320.0], Condition::Appearing) - .position([20.0, 140.0], Condition::Appearing) - .build(ui, || { - ui.text_wrapped(im_str!( - "The displayed color is passed to the button as four float values between \ - 0.0 - 1.0 (RGBA). If you don't care about the alpha component, it can be \ - disabled and it won't show up in the tooltip" - )); - - ui.text("This button ignores the alpha component:"); - ui.color_button(im_str!("Red color"), [1.0, 0.0, 0.0, 0.5]) - .alpha(false) - .build(); - - ui.spacing(); - ui.spacing(); - ui.spacing(); - ui.text_wrapped(im_str!( - "If you *do* care about the alpha component, you can choose how it's \ - displayed in the button and the tooltip" - )); - - ui.separator(); - ui.text_wrapped(im_str!( - "ColorPreview::Opaque (default) doesn't show the alpha component at all" - )); - ui.color_button(im_str!("Red + ColorPreview::Opaque"), [1.0, 0.0, 0.0, 0.5]) - .preview(ColorPreview::Opaque) - .build(); - - ui.separator(); - ui.text_wrapped(im_str!( - "ColorPreview::HalfAlpha divides the color area into two halves and uses a \ - checkerboard pattern in one half to illustrate the alpha component" - )); - ui.color_button( - im_str!("Red + ColorPreview::HalfAlpha"), - [1.0, 0.0, 0.0, 0.5], - ) - .preview(ColorPreview::HalfAlpha) - .build(); - - ui.separator(); - ui.text_wrapped(im_str!( - "ColorPreview::Alpha uses a checkerboard pattern in the entire color area to \ - illustrate the alpha component" - )); - ui.color_button(im_str!("Red + ColorPreview::Alpha"), [1.0, 0.0, 0.0, 0.5]) - .preview(ColorPreview::Alpha) - .build(); - }); -} diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 594d0b1..88b6fd9 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -479,8 +479,8 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { .build(); ui.input_float3(im_str!("input float3"), &mut state.vec3f) .build(); - ui.color_edit(im_str!("color 1"), &mut state.col1).build(); - ui.color_edit(im_str!("color 2"), &mut state.col2).build(); + ColorEdit::new(im_str!("color 1"), &mut state.col1).build(ui); + ColorEdit::new(im_str!("color 2"), &mut state.col2).build(ui); ui.tree_node(im_str!("Multi-component Widgets")).build(|| { ui.input_float2(im_str!("input float2"), &mut state.vec2f) @@ -519,13 +519,13 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { show options.", ); let misc_flags = { - let mut f = ImGuiColorEditFlags::empty(); - f.set(ImGuiColorEditFlags::HDR, s.hdr); - f.set(ImGuiColorEditFlags::AlphaPreviewHalf, s.alpha_half_preview); + let mut f = ColorEditFlags::empty(); + f.set(ColorEditFlags::HDR, s.hdr); + f.set(ColorEditFlags::ALPHA_PREVIEW_HALF, s.alpha_half_preview); if !s.alpha_half_preview { - f.set(ImGuiColorEditFlags::AlphaPreview, s.alpha_preview); + f.set(ColorEditFlags::ALPHA_PREVIEW, s.alpha_preview); } - f.set(ImGuiColorEditFlags::NoOptions, !s.options_menu); + f.set(ColorEditFlags::NO_OPTIONS, !s.options_menu); f }; @@ -536,22 +536,22 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { "Click on the colored square to open a color picker. CTRL+click on individual component to input value.\n", ); - ui.color_edit(im_str!("MyColor##1"), &mut s.color) + ColorEdit::new(im_str!("MyColor##1"), &mut s.color) .flags(misc_flags) .alpha(false) - .build(); + .build(ui); ui.text(im_str!("Color widget HSV with Alpha:")); - ui.color_edit(im_str!("MyColor##2"), &mut s.color) + ColorEdit::new(im_str!("MyColor##2"), &mut s.color) .flags(misc_flags) - .mode(ColorEditMode::HSV) - .build(); + .input_mode(ColorEditInputMode::HSV) + .build(ui); ui.text(im_str!("Color widget with Float Display:")); - ui.color_edit(im_str!("MyColor##2f"), &mut s.color) + ColorEdit::new(im_str!("MyColor##2f"), &mut s.color) .flags(misc_flags) .format(ColorFormat::Float) - .build(); + .build(ui); ui.text(im_str!("Color button with Picker:")); ui.same_line(0.0); @@ -562,11 +562,11 @@ CTRL+click on individual component to input value.\n", With the label(false) function you can pass a non-empty label which \ will only be used for the tooltip and picker popup.", ); - ui.color_edit(im_str!("MyColor##3"), &mut s.color) + ColorEdit::new(im_str!("MyColor##3"), &mut s.color) .flags(misc_flags) .inputs(false) .label(false) - .build(); + .build(ui); ui.text(im_str!("Color picker:")); ui.checkbox(im_str!("With Alpha"), &mut s.alpha); @@ -577,24 +577,24 @@ CTRL+click on individual component to input value.\n", ui.checkbox(im_str!("With Ref Color"), &mut s.ref_color); if s.ref_color { ui.same_line(0.0); - ui.color_edit(im_str!("##RefColor"), &mut s.ref_color_v) + ColorEdit::new(im_str!("##RefColor"), &mut s.ref_color_v) .flags(misc_flags) .inputs(false) - .build(); + .build(ui); } } - let mut b = ui - .color_picker(im_str!("MyColor##4"), &mut s.color) + let mut b = ColorPicker::new + (im_str!("MyColor##4"), &mut s.color) .flags(misc_flags) .alpha(s.alpha) .alpha_bar(s.alpha_bar) .side_preview(s.side_preview) - .rgb(true); + .display_rgb(true); if s.ref_color { b = b.reference_color(&s.ref_color_v) } - b.build(); + b.build(ui); }); } if ui @@ -674,7 +674,7 @@ CTRL+click on individual component to input value.\n", let items = &[im_str!("aaaa"), im_str!("bbbb"), im_str!("cccc"), im_str!("dddd"), im_str!("eeee")]; ui.combo(im_str!("Combo"), &mut state.stacked_modals_item, items, -1); - ui.color_edit(im_str!("color"), &mut state.stacked_modals_color).build(); + ColorEdit::new(im_str!("color"), &mut state.stacked_modals_color).build(ui); if ui.button(im_str!("Add another modal.."), [0.0, 0.0]) { ui.open_popup(im_str!("Stacked 2")) ; @@ -855,7 +855,7 @@ fn show_example_app_custom_rendering(ui: &Ui, state: &mut CustomRenderingState, .build(ui, || { ui.text("Primitives"); // TODO: Add DragFloat to change value of sz - ui.color_edit(im_str!("Color"), &mut state.col).build(); + ColorEdit::new(im_str!("Color"), &mut state.col).build(ui); let draw_list = ui.get_window_draw_list(); let p = ui.get_cursor_screen_pos(); let spacing = 8.0; diff --git a/src/color_editors.rs b/src/color_editors.rs deleted file mode 100644 index bc4150e..0000000 --- a/src/color_editors.rs +++ /dev/null @@ -1,426 +0,0 @@ -#![warn(missing_docs)] -use std::marker::PhantomData; -use std::ptr; - -use crate::legacy::ImGuiColorEditFlags; -use crate::sys; -use crate::{ImStr, Ui}; - -/// Mutable reference to an editable color value. -#[derive(Debug)] -pub enum EditableColor<'p> { - /// Color value with three float components (e.g. RGB). - Float3(&'p mut [f32; 3]), - /// Color value with four float components (e.g. RGBA). - Float4(&'p mut [f32; 4]), -} - -impl<'p> EditableColor<'p> { - /// Returns an unsafe mutable pointer to the color slice's buffer. - fn as_mut_ptr(&mut self) -> *mut f32 { - match *self { - EditableColor::Float3(ref mut value) => value.as_mut_ptr(), - EditableColor::Float4(ref mut value) => value.as_mut_ptr(), - } - } -} - -impl<'p> From<&'p mut [f32; 3]> for EditableColor<'p> { - fn from(value: &'p mut [f32; 3]) -> EditableColor<'p> { - EditableColor::Float3(value) - } -} - -impl<'p> From<&'p mut [f32; 4]> for EditableColor<'p> { - fn from(value: &'p mut [f32; 4]) -> EditableColor<'p> { - EditableColor::Float4(value) - } -} - -/// Color editor mode. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ColorEditMode { - /// Edit as RGB(A). - RGB, - /// Edit as HSV(A). - HSV, - /// Edit as hex (e.g. #AABBCC(DD)) - HEX, -} - -/// Color picker hue/saturation/value editor mode. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ColorPickerMode { - /// Use a bar for hue, rectangle for saturation/value. - HueBar, - /// Use a wheel for hue, triangle for saturation/value. - HueWheel, -} - -/// Color component formatting. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ColorFormat { - /// Display values formatted as 0..255. - U8, - /// Display values formatted as 0.0..1.0. - Float, -} - -/// Color editor preview style. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum ColorPreview { - /// Don't show the alpha component. - Opaque, - /// Half of the preview area shows the alpha component using a checkerboard pattern. - HalfAlpha, - /// Show the alpha component using a checkerboard pattern. - Alpha, -} - -/// Builder for a color editor widget. -#[must_use] -pub struct ColorEdit<'ui, 'p> { - label: &'p ImStr, - value: EditableColor<'p>, - flags: ImGuiColorEditFlags, - _phantom: PhantomData<&'ui Ui<'ui>>, -} - -impl<'ui, 'p> ColorEdit<'ui, 'p> { - /// Constructs a new color editor builder. - pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: EditableColor<'p>) -> Self { - ColorEdit { - label, - value, - flags: ImGuiColorEditFlags::empty(), - _phantom: PhantomData, - } - } - /// Replaces all current settings with the given flags. - #[inline] - pub fn flags(mut self, flags: ImGuiColorEditFlags) -> Self { - self.flags = flags; - self - } - /// Enables/disables the use of the alpha component. - #[inline] - pub fn alpha(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoAlpha, !value); - self - } - /// Enables/disables the picker that appears when clicking on colored square. - #[inline] - pub fn picker(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoPicker, !value); - self - } - /// Enables/disables toggling of the options menu when right-clicking on inputs or the small - /// preview. - #[inline] - pub fn options(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoOptions, !value); - self - } - /// Enables/disables the colored square preview next to the inputs. - #[inline] - pub fn small_preview(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoSmallPreview, !value); - self - } - /// Enables/disables the input sliders/text widgets. - #[inline] - pub fn inputs(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoInputs, !value); - self - } - /// Enables/disables the tooltip that appears when hovering the preview. - #[inline] - pub fn tooltip(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoTooltip, !value); - self - } - /// Enables/disables display of the inline text label (the label is in any case forwarded to - /// the tooltip and picker). - #[inline] - pub fn label(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoLabel, !value); - self - } - /// Enables/disables the vertical alpha bar/gradient in the color picker. - #[inline] - pub fn alpha_bar(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::AlphaBar, value); - self - } - /// Sets the preview style. - #[inline] - pub fn preview(mut self, preview: ColorPreview) -> Self { - self.flags.set( - ImGuiColorEditFlags::AlphaPreviewHalf, - preview == ColorPreview::HalfAlpha, - ); - self.flags.set( - ImGuiColorEditFlags::AlphaPreview, - preview == ColorPreview::Alpha, - ); - self - } - /// (WIP) Currently only disables 0.0..1.0 limits in RGBA edition. - /// - /// Note: you probably want to use ColorFormat::Float as well. - #[inline] - pub fn hdr(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::HDR, value); - self - } - /// Sets the color editor mode. - #[inline] - pub fn mode(mut self, mode: ColorEditMode) -> Self { - self.flags - .set(ImGuiColorEditFlags::RGB, mode == ColorEditMode::RGB); - self.flags - .set(ImGuiColorEditFlags::HSV, mode == ColorEditMode::HSV); - self.flags - .set(ImGuiColorEditFlags::HEX, mode == ColorEditMode::HEX); - self - } - /// Sets the formatting style of color components. - #[inline] - pub fn format(mut self, format: ColorFormat) -> Self { - self.flags - .set(ImGuiColorEditFlags::Uint8, format == ColorFormat::U8); - self.flags - .set(ImGuiColorEditFlags::Float, format == ColorFormat::Float); - self - } - /// Builds the color editor. - pub fn build(self) -> bool { - match self.value { - EditableColor::Float3(value) => unsafe { - sys::igColorEdit3(self.label.as_ptr(), value.as_mut_ptr(), self.flags.bits()) - }, - EditableColor::Float4(value) => unsafe { - sys::igColorEdit4(self.label.as_ptr(), value.as_mut_ptr(), self.flags.bits()) - }, - } - } -} - -/// Builder for a color picker widget. -#[must_use] -pub struct ColorPicker<'ui, 'p> { - label: &'p ImStr, - value: EditableColor<'p>, - flags: ImGuiColorEditFlags, - ref_color: Option<&'p [f32; 4]>, - _phantom: PhantomData<&'ui Ui<'ui>>, -} - -impl<'ui, 'p> ColorPicker<'ui, 'p> { - /// Constructs a new color picker builder. - pub fn new(_: &Ui<'ui>, label: &'p ImStr, value: EditableColor<'p>) -> Self { - ColorPicker { - label, - value, - flags: ImGuiColorEditFlags::empty(), - ref_color: None, - _phantom: PhantomData, - } - } - /// Replaces all current settings with the given flags. - #[inline] - pub fn flags(mut self, flags: ImGuiColorEditFlags) -> Self { - self.flags = flags; - self - } - /// Enables/disables the use of the alpha component. - #[inline] - pub fn alpha(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoAlpha, !value); - self - } - /// Enables/disables the colored square preview next to the inputs. - #[inline] - pub fn small_preview(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoSmallPreview, !value); - self - } - /// Enables/disables the input sliders/text widgets. - #[inline] - pub fn inputs(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoInputs, !value); - self - } - /// Enables/disables the tooltip that appears when hovering the preview. - #[inline] - pub fn tooltip(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoTooltip, !value); - self - } - /// Enables/disables display of the inline text label (the label is in any case forwarded to - /// the tooltip and picker). - #[inline] - pub fn label(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoLabel, !value); - self - } - /// Enables/disables the bigger color preview on the right side of the picker. - #[inline] - pub fn side_preview(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoSidePreview, !value); - self - } - /// Enables/disables the vertical alpha bar/gradient in the color picker. - #[inline] - pub fn alpha_bar(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::AlphaBar, value); - self - } - /// Sets the preview style. - #[inline] - pub fn preview(mut self, preview: ColorPreview) -> Self { - self.flags.set( - ImGuiColorEditFlags::AlphaPreviewHalf, - preview == ColorPreview::HalfAlpha, - ); - self.flags.set( - ImGuiColorEditFlags::AlphaPreview, - preview == ColorPreview::Alpha, - ); - self - } - /// Enables/disables the RGB inputs. - #[inline] - pub fn rgb(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::RGB, value); - self - } - /// Enables/disables the HSV inputs. - #[inline] - pub fn hsv(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::HSV, value); - self - } - /// Enables/disables the HEX input. - #[inline] - pub fn hex(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::HEX, value); - self - } - /// Sets the hue/saturation/value editor mode. - #[inline] - pub fn mode(mut self, mode: ColorPickerMode) -> Self { - self.flags.set( - ImGuiColorEditFlags::PickerHueBar, - mode == ColorPickerMode::HueBar, - ); - self.flags.set( - ImGuiColorEditFlags::PickerHueWheel, - mode == ColorPickerMode::HueWheel, - ); - self - } - /// Sets the formatting style of color components. - #[inline] - pub fn format(mut self, format: ColorFormat) -> Self { - self.flags - .set(ImGuiColorEditFlags::Uint8, format == ColorFormat::U8); - self.flags - .set(ImGuiColorEditFlags::Float, format == ColorFormat::Float); - self - } - /// Sets the shown reference color. - #[inline] - pub fn reference_color(mut self, ref_color: &'p [f32; 4]) -> Self { - self.ref_color = Some(ref_color); - self - } - /// Builds the color picker. - pub fn build(mut self) -> bool { - if let EditableColor::Float3(_) = self.value { - self.flags.insert(ImGuiColorEditFlags::NoAlpha); - } - let ref_color = self.ref_color.map(|c| c.as_ptr()).unwrap_or(ptr::null()); - unsafe { - sys::igColorPicker4( - self.label.as_ptr(), - self.value.as_mut_ptr(), - self.flags.bits(), - ref_color, - ) - } - } -} - -/// Builder for a color button widget. -#[must_use] -pub struct ColorButton<'ui, 'p> { - desc_id: &'p ImStr, - color: [f32; 4], - flags: ImGuiColorEditFlags, - size: [f32; 2], - _phantom: PhantomData<&'ui Ui<'ui>>, -} - -impl<'ui, 'p> ColorButton<'ui, 'p> { - /// Constructs a new color button builder. - pub fn new(_: &Ui<'ui>, desc_id: &'p ImStr, color: [f32; 4]) -> Self { - ColorButton { - desc_id, - color, - flags: ImGuiColorEditFlags::empty(), - size: [0.0, 0.0], - _phantom: PhantomData, - } - } - /// Replaces all current settings with the given flags. - #[inline] - pub fn flags(mut self, flags: ImGuiColorEditFlags) -> Self { - self.flags = flags; - self - } - /// Enables/disables the use of the alpha component. - #[inline] - pub fn alpha(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoAlpha, !value); - self - } - /// Enables/disables the tooltip that appears when hovering the preview. - #[inline] - pub fn tooltip(mut self, value: bool) -> Self { - self.flags.set(ImGuiColorEditFlags::NoTooltip, !value); - self - } - /// Sets the preview style. - #[inline] - pub fn preview(mut self, preview: ColorPreview) -> Self { - self.flags.set( - ImGuiColorEditFlags::AlphaPreviewHalf, - preview == ColorPreview::HalfAlpha, - ); - self.flags.set( - ImGuiColorEditFlags::AlphaPreview, - preview == ColorPreview::Alpha, - ); - self - } - /// Sets the button size. - /// - /// Use 0.0 for width and/or height to use the default size. - #[inline] - pub fn size(mut self, size: [f32; 2]) -> Self { - self.size = size.into(); - self - } - /// Builds the color button. - pub fn build(self) -> bool { - unsafe { - sys::igColorButton( - self.desc_id.as_ptr(), - self.color.into(), - self.flags.bits(), - self.size.into(), - ) - } - } -} diff --git a/src/legacy.rs b/src/legacy.rs index 5fe9f20..239612a 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -3,65 +3,13 @@ use bitflags::bitflags; use std::os::raw::c_int; use crate::string::ImStr; +use crate::widget::color_editors::*; use crate::widget::progress_bar::ProgressBar; use crate::window::{Window, WindowFlags}; use crate::Ui; -bitflags!( - /// Color edit flags - #[repr(C)] - pub struct ImGuiColorEditFlags: c_int { - /// ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read 3 components from the - /// input pointer). - const NoAlpha = 1; - /// ColorEdit: disable picker when clicking on colored square. - const NoPicker = 1 << 2; - /// ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. - const NoOptions = 1 << 3; - /// ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to - /// show only the inputs) - const NoSmallPreview = 1 << 4; - /// ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the - /// small preview colored square). - const NoInputs = 1 << 5; - /// ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. - const NoTooltip = 1 << 6; - /// ColorEdit, ColorPicker: disable display of inline text label (the label is still - /// forwarded to the tooltip and picker). - const NoLabel = 1 << 7; - /// ColorPicker: disable bigger color preview on right side of the picker, use small - /// colored square preview instead. - const NoSidePreview = 1 << 8; - /// ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. - const NoDragDrop = 1 << 9; - - /// ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. - const AlphaBar = 1 << 16; - /// ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a - /// checkerboard, instead of opaque. - const AlphaPreview = 1 << 17; - /// ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead - /// of opaque. - const AlphaPreviewHalf= 1 << 18; - /// (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you - /// probably want to use ImGuiColorEditFlags::Float flag as well). - const HDR = 1 << 19; - /// ColorEdit: choose one among RGB/HSV/HEX. ColorPicker: choose any combination using - /// RGB/HSV/HEX. - const RGB = 1 << 20; - const HSV = 1 << 21; - const HEX = 1 << 22; - /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. - const Uint8 = 1 << 23; - /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats - /// instead of 0..255 integers. No round-trip of value via integers. - const Float = 1 << 24; - /// ColorPicker: bar for Hue, rectangle for Sat/Value. - const PickerHueBar = 1 << 25; - /// ColorPicker: wheel for Hue, triangle for Sat/Value. - const PickerHueWheel = 1 << 26; - } -); +#[deprecated(since = "0.2.0", note = "use ColorEditFlags instead")] +pub type ImGuiColorEditFlags = ColorEditFlags; bitflags!( /// Flags for combo boxes @@ -360,3 +308,26 @@ impl<'ui> Ui<'ui> { ProgressBar::new(fraction) } } + +impl<'ui> Ui<'ui> { + #[deprecated(since = "0.2.0", note = "use imgui::ColorEdit::new(...) instead")] + pub fn color_edit<'p, V: Into>>( + &self, + label: &'p ImStr, + value: V, + ) -> ColorEdit<'p> { + ColorEdit::new(label, value.into()) + } + #[deprecated(since = "0.2.0", note = "use imgui::ColorPicker::new(...) instead")] + pub fn color_picker<'p, V: Into>>( + &self, + label: &'p ImStr, + value: V, + ) -> ColorPicker<'p> { + ColorPicker::new(label, value.into()) + } + #[deprecated(since = "0.2.0", note = "use imgui::ColorButton::new(...) instead")] + pub fn color_button<'p>(&self, desc_id: &'p ImStr, color: [f32; 4]) -> ColorButton<'p> { + ColorButton::new(desc_id, color.into()) + } +} diff --git a/src/lib.rs b/src/lib.rs index d4e4304..cf95548 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,10 +11,6 @@ use std::thread; pub use self::child_frame::ChildFrame; pub use self::clipboard::*; -pub use self::color_editors::{ - ColorButton, ColorEdit, ColorEditMode, ColorFormat, ColorPicker, ColorPickerMode, ColorPreview, - EditableColor, -}; pub use self::context::*; pub use self::drag::{ DragFloat, DragFloat2, DragFloat3, DragFloat4, DragFloatRange2, DragInt, DragInt2, DragInt3, @@ -47,6 +43,7 @@ pub use self::stacks::*; pub use self::string::*; pub use self::style::*; pub use self::trees::{CollapsingHeader, TreeNode}; +pub use self::widget::color_editors::*; pub use self::widget::progress_bar::*; pub use self::window::*; pub use self::window_draw_list::{ChannelsSplit, ImColor, WindowDrawList}; @@ -54,7 +51,6 @@ use internal::RawCast; mod child_frame; mod clipboard; -mod color_editors; mod context; mod drag; mod fonts; @@ -514,38 +510,6 @@ impl<'ui> Ui<'ui> { } } -// Widgets: Color Editor/Picker -impl<'ui> Ui<'ui> { - /// Constructs a new color editor builder. - pub fn color_edit<'p, V: Into>>( - &self, - label: &'p ImStr, - value: V, - ) -> ColorEdit<'ui, 'p> { - ColorEdit::new(self, label, value.into()) - } - /// Constructs a new color picker builder. - pub fn color_picker<'p, V: Into>>( - &self, - label: &'p ImStr, - value: V, - ) -> ColorPicker<'ui, 'p> { - ColorPicker::new(self, label, value.into()) - } - /// Constructs a new color button builder. - pub fn color_button<'p>(&self, desc_id: &'p ImStr, color: [f32; 4]) -> ColorButton<'ui, 'p> { - ColorButton::new(self, desc_id, color.into()) - } - /// Initialize current options (generally on application startup) if you want to select a - /// default format, picker type, etc. Users will be able to change many settings, unless you - /// use .options(false) in your widget builders. - pub fn set_color_edit_options(&self, flags: ImGuiColorEditFlags) { - unsafe { - sys::igSetColorEditOptions(flags.bits()); - } - } -} - // Widgets: Trees impl<'ui> Ui<'ui> { pub fn tree_node<'p>(&self, id: &'p ImStr) -> TreeNode<'ui, 'p> { diff --git a/src/widget/color_editors.rs b/src/widget/color_editors.rs new file mode 100644 index 0000000..af60459 --- /dev/null +++ b/src/widget/color_editors.rs @@ -0,0 +1,614 @@ +use bitflags::bitflags; +use std::ptr; + +use crate::string::ImStr; +use crate::sys; +use crate::Ui; + +/// Mutable reference to an editable color value. +#[derive(Debug)] +pub enum EditableColor<'a> { + /// Color value with three float components (e.g. RGB). + Float3(&'a mut [f32; 3]), + /// Color value with four float components (e.g. RGBA). + Float4(&'a mut [f32; 4]), +} + +impl<'a> EditableColor<'a> { + /// Returns an unsafe mutable pointer to the color slice's buffer. + fn as_mut_ptr(&mut self) -> *mut f32 { + match *self { + EditableColor::Float3(ref mut value) => value.as_mut_ptr(), + EditableColor::Float4(ref mut value) => value.as_mut_ptr(), + } + } +} + +impl<'a> From<&'a mut [f32; 3]> for EditableColor<'a> { + fn from(value: &'a mut [f32; 3]) -> EditableColor<'a> { + EditableColor::Float3(value) + } +} + +impl<'a> From<&'a mut [f32; 4]> for EditableColor<'a> { + fn from(value: &'a mut [f32; 4]) -> EditableColor<'a> { + EditableColor::Float4(value) + } +} + +/// Color editor input mode. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorEditInputMode { + /// Edit as RGB(A). + RGB, + /// Edit as HSV(A). + HSV, +} + +/// Color editor display mode. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorEditDisplayMode { + /// Display as RGB(A). + RGB, + /// Display as HSV(A). + HSV, + /// Display as hex (e.g. #AABBCC(DD)) + HEX, +} + +/// Color picker hue/saturation/value editor mode +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorPickerMode { + /// Use a bar for hue, rectangle for saturation/value. + HueBar, + /// Use a wheel for hue, triangle for saturation/value. + HueWheel, +} + +/// Color component formatting +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorFormat { + /// Display values formatted as 0..255. + U8, + /// Display values formatted as 0.0..1.0. + Float, +} + +/// Color editor preview style +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ColorPreview { + /// Don't show the alpha component. + Opaque, + /// Half of the preview area shows the alpha component using a checkerboard pattern. + HalfAlpha, + /// Show the alpha component using a checkerboard pattern. + Alpha, +} + +bitflags! { + /// Color edit flags + #[repr(transparent)] + pub struct ColorEditFlags: u32 { + /// ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read only 3 components of + /// the value). + const NO_ALPHA = sys::ImGuiColorEditFlags_NoAlpha; + /// ColorEdit: disable picker when clicking on colored square. + const NO_PICKER = sys::ImGuiColorEditFlags_NoPicker; + /// ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. + const NO_OPTIONS = sys::ImGuiColorEditFlags_NoOptions; + /// ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to + /// show only the inputs) + const NO_SMALL_PREVIEW = sys::ImGuiColorEditFlags_NoSmallPreview; + /// ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the + /// small preview colored square). + const NO_INPUTS = sys::ImGuiColorEditFlags_NoInputs; + /// ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. + const NO_TOOLTIP = sys::ImGuiColorEditFlags_NoTooltip; + /// ColorEdit, ColorPicker: disable display of inline text label (the label is still + /// forwarded to the tooltip and picker). + const NO_LABEL = sys::ImGuiColorEditFlags_NoLabel; + /// ColorPicker: disable bigger color preview on right side of the picker, use small + /// colored square preview instead. + const NO_SIDE_PREVIEW = sys::ImGuiColorEditFlags_NoSidePreview; + /// ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. + const NO_DRAG_DROP = sys::ImGuiColorEditFlags_NoDragDrop; + + /// ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. + const ALPHA_BAR = sys::ImGuiColorEditFlags_AlphaBar; + /// ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a + /// checkerboard, instead of opaque. + const ALPHA_PREVIEW = sys::ImGuiColorEditFlags_AlphaPreview; + /// ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead + /// of opaque. + const ALPHA_PREVIEW_HALF = sys::ImGuiColorEditFlags_AlphaPreviewHalf; + /// (WIP) ColorEdit: Currently onlys disable 0.0f..1.0f limits in RGBA editing (note: you + /// probably want to use `ColorEditFlags::FLOAT` as well). + const HDR = sys::ImGuiColorEditFlags_HDR; + /// ColorEdit: display only as RGB. ColorPicker: Enable RGB display. + const DISPLAY_RGB = sys::ImGuiColorEditFlags_DisplayRGB; + /// ColorEdit: display only as HSV. ColorPicker: Enable HSV display. + const DISPLAY_HSV = sys::ImGuiColorEditFlags_DisplayHSV; + /// ColorEdit: display only as HEX. ColorPicker: Enable Hex display. + const DISPLAY_HEX = sys::ImGuiColorEditFlags_DisplayHex; + /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. + const UINT8 = sys::ImGuiColorEditFlags_Uint8; + /// ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats + /// instead of 0..255 integers. No round-trip of value via integers. + const FLOAT = sys::ImGuiColorEditFlags_Float; + /// ColorPicker: bar for Hue, rectangle for Sat/Value. + const PICKER_HUE_BAR = sys::ImGuiColorEditFlags_PickerHueBar; + /// ColorPicker: wheel for Hue, triangle for Sat/Value. + const PICKER_HUE_WHEEL = sys::ImGuiColorEditFlags_PickerHueWheel; + /// ColorEdit, ColorPicker: input and output data in RGB format. + const INPUT_RGB = sys::ImGuiColorEditFlags_InputRGB; + /// ColorEdit, ColorPicker: input and output data in HSV format. + const INPUT_HSV = sys::ImGuiColorEditFlags_InputHSV; + } +} + +/// Builder for a color editor widget. +/// +/// # Examples +/// +/// ```no_run +/// # use imgui::*; +/// # let mut imgui = Context::create(); +/// # let ui = imgui.frame(); +/// # let mut color = [0.0, 0.0, 0.0, 1.0]; +/// let ce = ColorEdit::new(im_str!("color_edit"), &mut color); +/// if ce.build(&ui) { +/// println!("The color was changed"); +/// } +/// ``` +#[derive(Debug)] +#[must_use] +pub struct ColorEdit<'a> { + label: &'a ImStr, + value: EditableColor<'a>, + flags: ColorEditFlags, +} + +impl<'a> ColorEdit<'a> { + /// Constructs a new color editor builder. + pub fn new>>(label: &'a ImStr, value: T) -> ColorEdit<'a> { + ColorEdit { + label, + value: value.into(), + flags: ColorEditFlags::empty(), + } + } + /// Replaces all current settings with the given flags. + #[inline] + pub fn flags(mut self, flags: ColorEditFlags) -> Self { + self.flags = flags; + self + } + /// Enables/disables the use of the alpha component. + #[inline] + pub fn alpha(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_ALPHA, !value); + self + } + /// Enables/disables the picker that appears when clicking on colored square. + #[inline] + pub fn picker(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_PICKER, !value); + self + } + /// Enables/disables toggling of the options menu when right-clicking on inputs or the small + /// preview. + #[inline] + pub fn options(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_OPTIONS, !value); + self + } + /// Enables/disables the colored square preview next to the inputs. + #[inline] + pub fn small_preview(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_SMALL_PREVIEW, !value); + self + } + /// Enables/disables the input sliders/text widgets. + #[inline] + pub fn inputs(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_INPUTS, !value); + self + } + /// Enables/disables the tooltip that appears when hovering the preview. + #[inline] + pub fn tooltip(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_TOOLTIP, !value); + self + } + /// Enables/disables display of the inline text label (the label is in any case forwarded to + /// the tooltip and picker). + #[inline] + pub fn label(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_LABEL, !value); + self + } + /// Enables/disables the vertical alpha bar/gradient in the color picker. + #[inline] + pub fn alpha_bar(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::ALPHA_BAR, value); + self + } + /// Sets the preview style. + #[inline] + pub fn preview(mut self, preview: ColorPreview) -> Self { + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW_HALF, + preview == ColorPreview::HalfAlpha, + ); + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW, + preview == ColorPreview::Alpha, + ); + self + } + /// (WIP) Currently only disables 0.0..1.0 limits in RGBA edition. + /// + /// Note: you probably want to use ColorFormat::Float as well. + #[inline] + pub fn hdr(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::HDR, value); + self + } + /// Sets the data format for input and output data. + #[inline] + pub fn input_mode(mut self, input_mode: ColorEditInputMode) -> Self { + self.flags.set( + ColorEditFlags::INPUT_RGB, + input_mode == ColorEditInputMode::RGB, + ); + self.flags.set( + ColorEditFlags::INPUT_HSV, + input_mode == ColorEditInputMode::HSV, + ); + self + } + /// Sets the color editor display mode. + #[inline] + pub fn display_mode(mut self, mode: ColorEditDisplayMode) -> Self { + self.flags.set( + ColorEditFlags::DISPLAY_RGB, + mode == ColorEditDisplayMode::RGB, + ); + self.flags.set( + ColorEditFlags::DISPLAY_HSV, + mode == ColorEditDisplayMode::HSV, + ); + self.flags.set( + ColorEditFlags::DISPLAY_HEX, + mode == ColorEditDisplayMode::HEX, + ); + self + } + /// Sets the formatting style of color components. + #[inline] + pub fn format(mut self, format: ColorFormat) -> Self { + self.flags + .set(ColorEditFlags::UINT8, format == ColorFormat::U8); + self.flags + .set(ColorEditFlags::FLOAT, format == ColorFormat::Float); + self + } + /// Builds the color editor. + /// + /// Returns true if the color value was changed. + pub fn build(mut self, _: &Ui) -> bool { + if let EditableColor::Float3(_) = self.value { + self.flags.insert(ColorEditFlags::NO_ALPHA); + } + match self.value { + EditableColor::Float3(value) => unsafe { + sys::igColorEdit3( + self.label.as_ptr(), + value.as_mut_ptr(), + self.flags.bits() as _, + ) + }, + EditableColor::Float4(value) => unsafe { + sys::igColorEdit4( + self.label.as_ptr(), + value.as_mut_ptr(), + self.flags.bits() as _, + ) + }, + } + } +} + +/// Builder for a color picker widget. +/// +/// # Examples +/// +/// ```no_run +/// # use imgui::*; +/// # let mut imgui = Context::create(); +/// # let ui = imgui.frame(); +/// # let mut color = [0.0, 0.0, 0.0, 1.0]; +/// let cp = ColorPicker::new(im_str!("color_picker"), &mut color); +/// if cp.build(&ui) { +/// println!("A color was picked"); +/// } +/// ``` +#[derive(Debug)] +#[must_use] +pub struct ColorPicker<'a> { + label: &'a ImStr, + value: EditableColor<'a>, + flags: ColorEditFlags, + ref_color: Option<&'a [f32; 4]>, +} + +impl<'a> ColorPicker<'a> { + /// Constructs a new color picker builder. + pub fn new>>(label: &'a ImStr, value: T) -> ColorPicker<'a> { + ColorPicker { + label, + value: value.into(), + flags: ColorEditFlags::empty(), + ref_color: None, + } + } + /// Replaces all current settings with the given flags. + #[inline] + pub fn flags(mut self, flags: ColorEditFlags) -> Self { + self.flags = flags; + self + } + /// Enables/disables the use of the alpha component. + #[inline] + pub fn alpha(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_ALPHA, !value); + self + } + /// Enables/disables toggling of the options menu when right-clicking on inputs or the small + /// preview. + #[inline] + pub fn options(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_OPTIONS, !value); + self + } + /// Enables/disables the colored square preview next to the inputs. + #[inline] + pub fn small_preview(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_SMALL_PREVIEW, !value); + self + } + /// Enables/disables the input sliders/text widgets. + #[inline] + pub fn inputs(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_INPUTS, !value); + self + } + /// Enables/disables the tooltip that appears when hovering the preview. + #[inline] + pub fn tooltip(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_TOOLTIP, !value); + self + } + /// Enables/disables display of the inline text label (the label is in any case forwarded to + /// the tooltip and picker). + #[inline] + pub fn label(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_LABEL, !value); + self + } + /// Enables/disables the bigger color preview on the right side of the picker. + #[inline] + pub fn side_preview(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_SIDE_PREVIEW, !value); + self + } + /// Enables/disables the vertical alpha bar/gradient in the color picker. + #[inline] + pub fn alpha_bar(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::ALPHA_BAR, value); + self + } + /// Sets the preview style. + #[inline] + pub fn preview(mut self, preview: ColorPreview) -> Self { + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW_HALF, + preview == ColorPreview::HalfAlpha, + ); + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW, + preview == ColorPreview::Alpha, + ); + self + } + /// Sets the data format for input and output data. + #[inline] + pub fn input_mode(mut self, input_mode: ColorEditInputMode) -> Self { + self.flags.set( + ColorEditFlags::INPUT_RGB, + input_mode == ColorEditInputMode::RGB, + ); + self.flags.set( + ColorEditFlags::INPUT_HSV, + input_mode == ColorEditInputMode::HSV, + ); + self + } + /// Enables/disables displaying the value as RGB. + #[inline] + pub fn display_rgb(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::DISPLAY_RGB, value); + self + } + /// Enables/disables displaying the value as HSV. + #[inline] + pub fn display_hsv(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::DISPLAY_HSV, value); + self + } + /// Enables/disables displaying the value as hex. + #[inline] + pub fn display_hex(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::DISPLAY_HEX, value); + self + } + /// Sets the hue/saturation/value editor mode. + #[inline] + pub fn mode(mut self, mode: ColorPickerMode) -> Self { + self.flags.set( + ColorEditFlags::PICKER_HUE_BAR, + mode == ColorPickerMode::HueBar, + ); + self.flags.set( + ColorEditFlags::PICKER_HUE_WHEEL, + mode == ColorPickerMode::HueWheel, + ); + self + } + /// Sets the formatting style of color components. + #[inline] + pub fn format(mut self, format: ColorFormat) -> Self { + self.flags + .set(ColorEditFlags::UINT8, format == ColorFormat::U8); + self.flags + .set(ColorEditFlags::FLOAT, format == ColorFormat::Float); + self + } + /// Sets the shown reference color. + #[inline] + pub fn reference_color(mut self, ref_color: &'a [f32; 4]) -> Self { + self.ref_color = Some(ref_color); + self + } + /// Builds the color picker. + /// + /// Returns true if the color value was changed. + pub fn build(mut self, _: &Ui) -> bool { + if let EditableColor::Float3(_) = self.value { + self.flags.insert(ColorEditFlags::NO_ALPHA); + } + let ref_color = self.ref_color.map(|c| c.as_ptr()).unwrap_or(ptr::null()); + unsafe { + sys::igColorPicker4( + self.label.as_ptr(), + self.value.as_mut_ptr(), + self.flags.bits() as _, + ref_color, + ) + } + } +} + +/// Builder for a color button widget. +/// +/// # Examples +/// +/// ```no_run +/// # use imgui::*; +/// # let mut imgui = Context::create(); +/// # let ui = imgui.frame(); +/// ColorButton::new(im_str!("color_button"), [1.0, 0.0, 0.0, 1.0]) +/// .build(&ui); +/// ``` +#[derive(Debug, Clone)] +#[must_use] +pub struct ColorButton<'a> { + desc_id: &'a ImStr, + color: [f32; 4], + flags: ColorEditFlags, + size: [f32; 2], +} + +impl<'a> ColorButton<'a> { + /// Constructs a new color button builder. + pub fn new(desc_id: &ImStr, color: [f32; 4]) -> ColorButton { + ColorButton { + desc_id, + color, + flags: ColorEditFlags::empty(), + size: [0.0, 0.0], + } + } + /// Replaces all current settings with the given flags. + #[inline] + pub fn flags(mut self, flags: ColorEditFlags) -> Self { + self.flags = flags; + self + } + /// Enables/disables the use of the alpha component. + #[inline] + pub fn alpha(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_ALPHA, !value); + self + } + /// Enables/disables the tooltip that appears when hovering the preview. + #[inline] + pub fn tooltip(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_TOOLTIP, !value); + self + } + /// Sets the preview style. + #[inline] + pub fn preview(mut self, preview: ColorPreview) -> Self { + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW_HALF, + preview == ColorPreview::HalfAlpha, + ); + self.flags.set( + ColorEditFlags::ALPHA_PREVIEW, + preview == ColorPreview::Alpha, + ); + self + } + /// Sets the data format for input data. + #[inline] + pub fn input_mode(mut self, input_mode: ColorEditInputMode) -> Self { + self.flags.set( + ColorEditFlags::INPUT_RGB, + input_mode == ColorEditInputMode::RGB, + ); + self.flags.set( + ColorEditFlags::INPUT_HSV, + input_mode == ColorEditInputMode::HSV, + ); + self + } + /// Enables/disables using the button as drag&drop source. + pub fn drag_drop(mut self, value: bool) -> Self { + self.flags.set(ColorEditFlags::NO_DRAG_DROP, !value); + self + } + /// Sets the button size. + /// + /// Use 0.0 for width and/or height to use the default size. + #[inline] + pub fn size(mut self, size: [f32; 2]) -> Self { + self.size = size; + self + } + /// Builds the color button. + /// + /// Returns true if this color button was clicked. + pub fn build(self, _: &Ui) -> bool { + unsafe { + sys::igColorButton( + self.desc_id.as_ptr(), + self.color.into(), + self.flags.bits() as _, + self.size.into(), + ) + } + } +} + +/// # Widgets: Color Editor/Picker +impl<'ui> Ui<'ui> { + /// Initialize current options (generally on application startup) if you want to select a + /// default format, picker type, etc. Users will be able to change many settings, unless you + /// use .options(false) in your widget builders. + pub fn set_color_edit_options(&self, flags: ColorEditFlags) { + unsafe { + sys::igSetColorEditOptions(flags.bits() as i32); + } + } +} diff --git a/src/widget/mod.rs b/src/widget/mod.rs index cb7e7f4..d67a404 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -1,3 +1,4 @@ +pub mod color_editors; pub mod misc; pub mod progress_bar; pub mod text;