boing 0.7.0

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

//! [`Tab`].

use crate::prelude::*;

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

#[subcontrol(handle = "uiTab")]
#[derive(Container)]
#[container(
    child_count = "uiTabNumPages",
    remove_child = "uiTabDelete",
)]
pub struct Tab;

impl<'ui> Tab<'ui> {
    /// Appends a new page with the given name, returning its index.
    ///
    /// The new page is appended to the right of the tab.
    pub fn push_page(
        &self,
        control: &'ui impl DerefMut<Target = Control>,
        name: impl Into<Vec<u8>>,
    ) -> Result<NonNegativeInt, crate::Error> {
        let index = self.child_count();
        let name = self.ui.make_cstring(name)?;
        control.make_child();
        unsafe { uiTabAppend(self.as_ptr(), name.as_ptr(), control.as_ptr()) };

        Ok(index)
    }

    /// Inserts a new page with the given name before an existing page, returning the index of the
    /// new page.
    ///
    /// # Arguments
    ///
    /// `before` is the index of the existing page that follows the new page. The returned index is
    /// equivalent to `before`.
    ///
    /// # Panics
    ///
    /// Panics if `before` is out of bounds.
    pub fn insert_item(
        &self,
        before: impl Into<NonNegativeInt>,
        control: &'ui impl DerefMut<Target = Control>,
        name: impl Into<Vec<u8>>,
    ) -> Result<NonNegativeInt, crate::Error> {
        let before = before.into();
        assert!(self.contains_child(before));
        let name = self.ui.make_cstring(name)?;
        control.make_child();
        unsafe { uiTabInsertAt(self.as_ptr(), name.as_ptr(), before.to_libui(), control.as_ptr()) };

        Ok(before)
    }

    /// Determines if the page at the given index is margined.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn is_page_margined(&self, index: impl Into<NonNegativeInt>) -> bool {
        let index = index.into();
        assert!(self.contains_child(index));

        bool_from_libui(unsafe { uiTabMargined(self.as_ptr(), index.to_libui()) })
    }

    /// Sets whether or not the page at the given index should be margined.
    ///
    /// # Panics
    ///
    /// Panics if `index` is out of bounds.
    pub fn set_page_margined(&self, index: impl Into<NonNegativeInt>, value: bool) {
        let index = index.into();
        assert!(self.contains_child(index));

        unsafe { uiTabSetMargined(self.as_ptr(), index.to_libui(), value.into()) };
    }
}