dear_implot/context/
token.rs1use super::callbacks::PlotScopeGuard;
2use super::core::PlotContextBinding;
3use crate::sys;
4use dear_imgui_rs::{ContextAliveToken, DrawListMut, Ui};
5use std::marker::PhantomData;
6use std::rc::Rc;
7
8pub struct PlotToken<'ui> {
12 binding: PlotContextBinding,
13 imgui_alive: Option<ContextAliveToken>,
14 ui: &'ui Ui,
15 _scope: PlotScopeGuard,
16 _lifetime: PhantomData<&'ui ()>,
17}
18
19impl<'ui> PlotToken<'ui> {
20 pub(crate) fn new(
22 binding: PlotContextBinding,
23 imgui_alive: Option<ContextAliveToken>,
24 ui: &'ui Ui,
25 ) -> Self {
26 Self {
27 binding,
28 imgui_alive,
29 ui,
30 _scope: PlotScopeGuard::new(),
31 _lifetime: PhantomData,
32 }
33 }
34
35 pub fn end(self) {
40 }
42
43 pub fn plot_draw_list(&self) -> Option<DrawListMut<'_>> {
45 self.assert_alive();
46 let _guard = self.binding.bind("dear-implot: PlotToken");
47 let draw_list = unsafe { sys::ImPlot_GetPlotDrawList() };
48 if draw_list.is_null() {
49 None
50 } else {
51 Some(unsafe { DrawListMut::from_raw_mut(self.ui, draw_list) })
52 }
53 }
54
55 pub fn push_plot_clip_rect(&self, expand: f32) -> PlotClipRectToken<'_> {
60 assert!(
61 expand.is_finite(),
62 "PlotToken::push_plot_clip_rect() expand must be finite"
63 );
64 self.assert_alive();
65 let _guard = self.binding.bind("dear-implot: PlotToken");
66 unsafe { sys::ImPlot_PushPlotClipRect(expand) };
67 PlotClipRectToken {
68 binding: self.binding,
69 imgui_alive: self.imgui_alive.clone(),
70 was_popped: false,
71 _lifetime: PhantomData,
72 _not_send_or_sync: PhantomData,
73 }
74 }
75
76 fn assert_alive(&self) {
77 assert_imgui_alive(&self.imgui_alive, "dear-implot: PlotToken");
78 }
79}
80
81impl<'ui> Drop for PlotToken<'ui> {
82 fn drop(&mut self) {
83 self.assert_alive();
84 let _guard = self.binding.bind("dear-implot: PlotToken");
85 unsafe {
86 sys::ImPlot_EndPlot();
87 }
88 }
89}
90
91#[must_use]
93pub struct PlotClipRectToken<'plot> {
94 binding: PlotContextBinding,
95 imgui_alive: Option<ContextAliveToken>,
96 was_popped: bool,
97 _lifetime: PhantomData<&'plot ()>,
98 _not_send_or_sync: PhantomData<Rc<()>>,
99}
100
101impl PlotClipRectToken<'_> {
102 pub fn pop(mut self) {
104 self.pop_inner();
105 }
106
107 pub fn end(mut self) {
109 self.pop_inner();
110 }
111
112 fn pop_inner(&mut self) {
113 if self.was_popped {
114 panic!("Attempted to pop an ImPlot plot clip rect token twice.");
115 }
116 assert_imgui_alive(&self.imgui_alive, "dear-implot: PlotClipRectToken");
117 let _guard = self.binding.bind("dear-implot: PlotClipRectToken");
118 unsafe { sys::ImPlot_PopPlotClipRect() };
119 self.was_popped = true;
120 }
121}
122
123impl Drop for PlotClipRectToken<'_> {
124 fn drop(&mut self) {
125 if !self.was_popped {
126 self.pop_inner();
127 }
128 }
129}
130
131fn assert_imgui_alive(alive: &Option<ContextAliveToken>, caller: &str) {
132 if let Some(alive) = alive {
133 assert!(alive.is_alive(), "{caller}: ImGui context has been dropped");
134 }
135}