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, 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 {
104    prev: *mut sys::ImGuiStorage,
105}
106
107impl Drop for StateStorageToken {
108    fn drop(&mut self) {
109        unsafe { sys::igSetStateStorage(self.prev) }
110    }
111}
112
113impl crate::ui::Ui {
114    /// Returns the current window's state storage.
115    #[doc(alias = "GetStateStorage")]
116    pub fn state_storage(&self) -> StateStorage<'_> {
117        unsafe { StateStorage::from_raw(sys::igGetStateStorage()) }
118    }
119
120    /// Overrides the current state storage until the returned token is dropped.
121    #[doc(alias = "SetStateStorage")]
122    pub fn push_state_storage(&self, storage: &mut sys::ImGuiStorage) -> StateStorageToken {
123        unsafe {
124            let prev = sys::igGetStateStorage();
125            sys::igSetStateStorage(storage as *mut sys::ImGuiStorage);
126            StateStorageToken { prev }
127        }
128    }
129
130    /// Set the storage ID for the next item.
131    #[doc(alias = "SetNextItemStorageID")]
132    pub fn set_next_item_storage_id(&self, storage_id: Id) {
133        unsafe { sys::igSetNextItemStorageID(storage_id.raw()) }
134    }
135}