boing 0.7.0

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

//! A horizontal bar that continuously fills as an action progresses.

use crate::prelude::*;

impl Ui {
    /// Creates a new [`ProgressBar`].
    pub fn create_progress_bar<'ui>(&'ui self) -> Result<&'ui mut ProgressBar, crate::Error> {
        unsafe { call_libui_new_fn!(ui: self, fn: uiNewProgressBar() -> ProgressBar) }
    }
}

/// A horizontal bar that continuously fills as an action progresses.
#[subcontrol(handle = "uiProgressBar")]
pub struct ProgressBar;

#[derive(Clone, Copy, Eq, PartialEq)]
pub enum State {
    Value(NonNegativeInt),
    Indefinite,
}

impl ProgressBar<'_> {
    /// The current state of this progress bar.
    ///
    /// This returns `State::Value(0)` by default.
    pub fn state(&self) -> State {
        let value = unsafe { uiProgressBarValue(self.as_ptr()) };

        if value >= 0 {
            debug_assert!(value <= 100, "invalid progress bar value");

            State::Value(unsafe { NonNegativeInt::from_libui(value) })
        } else {
            debug_assert_eq!(value, -1, "invalid progress bar value");

            State::Indefinite
        }
    }

    pub fn value(&self) -> Option<NonNegativeInt> {
        match self.state() {
            State::Value(it) => Some(it),
            State::Indefinite => None,
        }
    }

    pub fn is_indefinite(&self) -> bool {
        matches!(self.state(), State::Indefinite)
    }

    /// Sets the value of this progress bar.
    ///
    /// [`state`](Self::state) will return `State::Value(...)` after this is called.
    ///
    /// # Panics
    ///
    /// Panics if `value` is greater than 100.
    pub fn set_value(&self, value: impl Into<NonNegativeInt>) {
        let value = value.into().to_libui();
        assert!(value <= 100);

        unsafe { uiProgressBarSetValue(self.as_ptr(), value) };
    }

    /// Marks this progress bar as being indefinite.
    ///
    /// By convention, this causes the progress bar to continuously rotate a colored inner bar,
    /// indicating that an action is in progress but it is unknown when the action will complete.
    ///
    /// To mark this progress bar as being definite again, call [`set_value`](Self::set_value) with
    /// the progress.
    pub fn set_as_indefinite(&self) {
        unsafe { uiProgressBarSetValue(self.as_ptr(), -1) };
    }
}