1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 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()) };
    }
}