boing 0.7.0

A safe wrapper over libui-ng-sys
Documentation
// SPDX-License-Identifier: MPL-2.0

//! [`Slider`].

use crate::prelude::*;

impl Ui {
    /// Creates a new [`Slider`].
    ///
    /// # Arguments
    ///
    /// `min` is the initial minimum value and `max` is the initial maximum value of the slider.
    ///
    /// # Panics
    ///
    /// Panics if `min` is greater than `max`.
    pub fn create_slider<'ui>(
        &'ui self,
        min: impl Into<NonNegativeInt>,
        max: impl Into<NonNegativeInt>,
    ) -> Result<&'ui mut Slider, crate::Error> {
        let min = min.into();
        let max = max.into();
        assert!(min <= max, "minimum must be less than or equal to maximum");

        unsafe {
            call_libui_new_fn!(
                ui: self,
                fn: uiNewSlider(min.to_libui(), max.to_libui()) -> Slider,
            )
        }
    }
}

#[subcontrol(handle = "uiSlider")]
pub struct Slider;

impl<'ui> Slider<'ui> {
    /// The current value of this slider.
    #[inline]
    pub fn value(&self) -> NonNegativeInt {
        unsafe { NonNegativeInt::from_libui(uiSliderValue(self.as_ptr())) }
    }

    /// Sets the value of this slider.
    ///
    /// This overrides the value set by the user.
    #[inline]
    pub fn set_value(&self, value: impl Into<NonNegativeInt>) {
        // FIXME: should we panic if `value` is outside the range?
        unsafe { uiSliderSetValue(self.as_ptr(), value.into().to_libui()) };
    }

    /// Determines if this slider has a tooltip.
    #[inline]
    pub fn has_tooltip(&self) -> bool {
        bool_from_libui(unsafe { uiSliderHasToolTip(self.as_ptr()) })
    }

    /// Sets whether or not this slider has a tooltip.
    #[inline]
    pub fn set_has_tooltip(&self, value: bool) {
        unsafe { uiSliderSetHasToolTip(self.as_ptr(), value.into()) };
    }

    /// Sets a callback for when the user changes the slider value.
    ///
    /// This callback is unset by default. This is not activated when [`set_value`](Self::Set_value)
    /// is called.
    #[bind_callback(fn = "uiSliderOnChanged")]
    pub fn on_changed(&self, f: fn()) {
        f();
    }

    /// Sets a callback for when the user releases the slider handle from dragging.
    ///
    /// This callback is unset by default.
    #[bind_callback(fn = "uiSliderOnReleased")]
    pub fn on_released(&self, f: fn()) {
        f();
    }

    /// Sets the minimum and maximum values of this slider.
    ///
    /// This overrides the range supplied to [`Ui::create_slider`].
    ///
    /// # Panics
    ///
    /// Panics if `min` is greater than `max`.
    pub fn set_range(&self, min: impl Into<NonNegativeInt>, max: impl Into<NonNegativeInt>) {
        let min = min.into();
        let max = max.into();
        assert!(min <= max, "minimum must be less than or equal to maximum");

        unsafe { uiSliderSetRange(self.as_ptr(), min.to_libui(), max.to_libui()) };

        // Clamp current value to nearest value in range.
        // FIXME: should we do this before or after the call to `uiSliderSetRange`?
        let value = self.value();
        if value > max {
            self.set_value(max);
        } else if value < min {
            self.set_value(min);
        }
    }
}