Skip to main content

dear_imgui_rs/
state_storage.rs

1//! State storage utilities
2//!
3//! Dear ImGui provides a per-window key/value storage (`ImGuiStorage`) that is
4//! used by many widgets and can also be used by custom widgets to persist state.
5//!
6use crate::{Id, Ui, sys};
7use std::marker::PhantomData;
8use std::ptr::NonNull;
9
10/// A non-owning reference to an `ImGuiStorage` belonging to the current context.
11#[derive(Copy, Clone, Debug)]
12pub struct StateStorage<'ui> {
13    raw: NonNull<sys::ImGuiStorage>,
14    _phantom: PhantomData<&'ui mut sys::ImGuiStorage>,
15}
16
17impl<'ui> StateStorage<'ui> {
18    /// # Safety
19    /// `raw` must be a valid, non-null pointer to an `ImGuiStorage`.
20    pub unsafe fn from_raw(raw: *mut sys::ImGuiStorage) -> Self {
21        let raw = NonNull::new(raw).expect("StateStorage::from_raw() requires non-null pointer");
22        Self {
23            raw,
24            _phantom: PhantomData,
25        }
26    }
27
28    /// Returns the raw `ImGuiStorage*`.
29    pub fn as_raw(self) -> *mut sys::ImGuiStorage {
30        self.raw.as_ptr()
31    }
32
33    /// Clears all storage entries.
34    pub fn clear(&mut self) {
35        unsafe { sys::ImGuiStorage_Clear(self.raw.as_ptr()) }
36    }
37
38    pub fn get_int(&self, key: Id, default: i32) -> i32 {
39        unsafe { sys::ImGuiStorage_GetInt(self.raw.as_ptr(), key.raw(), default) }
40    }
41
42    pub fn set_int(&mut self, key: Id, value: i32) {
43        unsafe { sys::ImGuiStorage_SetInt(self.raw.as_ptr(), key.raw(), value) }
44    }
45
46    pub fn get_bool(&self, key: Id, default: bool) -> bool {
47        unsafe { sys::ImGuiStorage_GetBool(self.raw.as_ptr(), key.raw(), default) }
48    }
49
50    pub fn set_bool(&mut self, key: Id, value: bool) {
51        unsafe { sys::ImGuiStorage_SetBool(self.raw.as_ptr(), key.raw(), value) }
52    }
53
54    pub fn get_float(&self, key: Id, default: f32) -> f32 {
55        unsafe { sys::ImGuiStorage_GetFloat(self.raw.as_ptr(), key.raw(), default) }
56    }
57
58    pub fn set_float(&mut self, key: Id, value: f32) {
59        unsafe { sys::ImGuiStorage_SetFloat(self.raw.as_ptr(), key.raw(), value) }
60    }
61}
62
63/// Owns an `ImGuiStorage` and clears it on drop.
64///
65/// This is useful when you want to keep widget state outside of the current
66/// window storage (e.g. sharing state across windows or providing custom storage
67/// for a widget subtree via `Ui::push_state_storage`).
68#[derive(Debug, Default)]
69pub struct OwnedStateStorage {
70    raw: sys::ImGuiStorage,
71}
72
73impl OwnedStateStorage {
74    pub fn new() -> Self {
75        Self::default()
76    }
77
78    pub fn as_mut(&mut self) -> &mut sys::ImGuiStorage {
79        &mut self.raw
80    }
81
82    pub fn as_ref(&self) -> &sys::ImGuiStorage {
83        &self.raw
84    }
85
86    pub fn as_raw_mut(&mut self) -> *mut sys::ImGuiStorage {
87        &mut self.raw as *mut sys::ImGuiStorage
88    }
89
90    pub fn as_raw(&self) -> *const sys::ImGuiStorage {
91        &self.raw as *const sys::ImGuiStorage
92    }
93}
94
95impl Drop for OwnedStateStorage {
96    fn drop(&mut self) {
97        unsafe { sys::ImGuiStorage_Clear(self.as_raw_mut()) }
98    }
99}
100
101/// RAII token that restores the previous state storage on drop.
102#[must_use]
103pub struct StateStorageToken<'ui, 'storage> {
104    prev: *mut sys::ImGuiStorage,
105    _marker: PhantomData<(&'ui Ui, &'storage mut sys::ImGuiStorage)>,
106}
107
108impl Drop for StateStorageToken<'_, '_> {
109    fn drop(&mut self) {
110        unsafe { sys::igSetStateStorage(self.prev) }
111    }
112}
113
114impl crate::ui::Ui {
115    /// Returns the current window's state storage.
116    #[doc(alias = "GetStateStorage")]
117    pub fn state_storage(&self) -> StateStorage<'_> {
118        unsafe { StateStorage::from_raw(sys::igGetStateStorage()) }
119    }
120
121    /// Overrides the current state storage until the returned token is dropped.
122    #[doc(alias = "SetStateStorage")]
123    pub fn push_state_storage<'storage>(
124        &self,
125        storage: &'storage mut sys::ImGuiStorage,
126    ) -> StateStorageToken<'_, 'storage> {
127        unsafe {
128            let prev = sys::igGetStateStorage();
129            sys::igSetStateStorage(storage as *mut sys::ImGuiStorage);
130            StateStorageToken {
131                prev,
132                _marker: PhantomData,
133            }
134        }
135    }
136
137    /// Set the storage ID for the next item.
138    #[doc(alias = "SetNextItemStorageID")]
139    pub fn set_next_item_storage_id(&self, storage_id: Id) {
140        unsafe { sys::igSetNextItemStorageID(storage_id.raw()) }
141    }
142}