1use std::mem;
2use std::os::raw::{c_char, c_void};
3use std::ptr;
4use std::thread;
5
6use crate::context::Context;
7use crate::fonts::atlas::FontId;
8use crate::internal::RawCast;
9use crate::style::{StyleColor, StyleVar};
10use crate::sys;
11use crate::{Id, Ui};
12
13impl<'ui> Ui<'ui> {
15 #[doc(alias = "PushFont")]
38 pub fn push_font(&self, id: FontId) -> FontStackToken<'_> {
39 let fonts = self.fonts();
40 let font = fonts
41 .get_font(id)
42 .expect("Font atlas did not contain the given font");
43 unsafe { sys::igPushFont(font.raw() as *const _ as *mut _) };
44 FontStackToken::new(self)
45 }
46 #[doc(alias = "PushStyleColorVec4")]
62 pub fn push_style_color(
63 &self,
64 style_color: StyleColor,
65 color: [f32; 4],
66 ) -> ColorStackToken<'_> {
67 unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into()) };
68 ColorStackToken::new(self)
69 }
70
71 #[deprecated = "deprecated in 0.7.0. Use `push_style_color` multiple times for similar effect."]
92 pub fn push_style_colors<'a, I>(&self, style_colors: I) -> MultiColorStackToken
93 where
94 I: IntoIterator<Item = &'a (StyleColor, [f32; 4])>,
95 {
96 let mut count = 0;
97 for &(style_color, color) in style_colors {
98 unsafe { sys::igPushStyleColor_Vec4(style_color as i32, color.into()) };
99 count += 1;
100 }
101 MultiColorStackToken {
102 count,
103 ctx: self.ctx,
104 }
105 }
106 #[doc(alias = "PushStyleVar")]
122 pub fn push_style_var(&self, style_var: StyleVar) -> StyleStackToken<'_> {
123 unsafe { push_style_var(style_var) };
124 StyleStackToken::new(self)
125 }
126 #[deprecated = "deprecated in 0.7.0. Use `push_style_var` multiple times for similar effect."]
145 pub fn push_style_vars<'a, I>(&self, style_vars: I) -> MultiStyleStackToken
146 where
147 I: IntoIterator<Item = &'a StyleVar>,
148 {
149 let mut count = 0;
150 for &style_var in style_vars {
151 unsafe { push_style_var(style_var) };
152 count += 1;
153 }
154 MultiStyleStackToken {
155 count,
156 ctx: self.ctx,
157 }
158 }
159}
160
161create_token!(
162 pub struct FontStackToken<'ui>;
165
166 drop { sys::igPopFont() }
168);
169
170impl FontStackToken<'_> {
171 pub fn pop(self) {
173 self.end()
174 }
175}
176
177create_token!(
178 pub struct ColorStackToken<'ui>;
181
182 drop { sys::igPopStyleColor(1) }
184);
185
186impl ColorStackToken<'_> {
187 pub fn pop(self) {
189 self.end()
190 }
191}
192
193#[must_use]
195pub struct MultiColorStackToken {
196 count: usize,
197 ctx: *const Context,
198}
199
200impl MultiColorStackToken {
201 #[doc(alias = "PopStyleColor")]
203 pub fn pop(mut self, _: &Ui<'_>) {
204 self.ctx = ptr::null();
205 unsafe { sys::igPopStyleColor(self.count as i32) };
206 }
207}
208
209impl Drop for MultiColorStackToken {
210 fn drop(&mut self) {
211 if !self.ctx.is_null() && !thread::panicking() {
212 panic!("A ColorStackToken was leaked. Did you call .pop()?");
213 }
214 }
215}
216
217create_token!(
218 pub struct StyleStackToken<'ui>;
221
222 drop { sys::igPopStyleVar(1) }
224);
225
226impl StyleStackToken<'_> {
227 pub fn pop(self) {
229 self.end()
230 }
231}
232
233#[must_use]
235pub struct MultiStyleStackToken {
236 count: usize,
237 ctx: *const Context,
238}
239
240impl MultiStyleStackToken {
241 #[doc(alias = "PopStyleVar")]
243 pub fn pop(mut self, _: &Ui<'_>) {
244 self.ctx = ptr::null();
245 unsafe { sys::igPopStyleVar(self.count as i32) };
246 }
247}
248
249impl Drop for MultiStyleStackToken {
250 fn drop(&mut self) {
251 if !self.ctx.is_null() && !thread::panicking() {
252 panic!("A StyleStackToken was leaked. Did you call .pop()?");
253 }
254 }
255}
256
257#[inline]
258unsafe fn push_style_var(style_var: StyleVar) {
259 use crate::style::StyleVar::*;
260 use crate::sys::{igPushStyleVar_Float, igPushStyleVar_Vec2};
261 match style_var {
262 Alpha(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_Alpha as i32, v),
263 WindowPadding(v) => igPushStyleVar_Vec2(sys::ImGuiStyleVar_WindowPadding as i32, v.into()),
264 WindowRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_WindowRounding as i32, v),
265 WindowBorderSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_WindowBorderSize as i32, v),
266 WindowMinSize(v) => igPushStyleVar_Vec2(sys::ImGuiStyleVar_WindowMinSize as i32, v.into()),
267 WindowTitleAlign(v) => {
268 igPushStyleVar_Vec2(sys::ImGuiStyleVar_WindowTitleAlign as i32, v.into())
269 }
270 ChildRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_ChildRounding as i32, v),
271 ChildBorderSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_ChildBorderSize as i32, v),
272 PopupRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_PopupRounding as i32, v),
273 PopupBorderSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_PopupBorderSize as i32, v),
274 FramePadding(v) => igPushStyleVar_Vec2(sys::ImGuiStyleVar_FramePadding as i32, v.into()),
275 FrameRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_FrameRounding as i32, v),
276 FrameBorderSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_FrameBorderSize as i32, v),
277 ItemSpacing(v) => igPushStyleVar_Vec2(sys::ImGuiStyleVar_ItemSpacing as i32, v.into()),
278 ItemInnerSpacing(v) => {
279 igPushStyleVar_Vec2(sys::ImGuiStyleVar_ItemInnerSpacing as i32, v.into())
280 }
281 IndentSpacing(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_IndentSpacing as i32, v),
282 ScrollbarSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_ScrollbarSize as i32, v),
283 ScrollbarRounding(v) => {
284 igPushStyleVar_Float(sys::ImGuiStyleVar_ScrollbarRounding as i32, v)
285 }
286 GrabMinSize(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_GrabMinSize as i32, v),
287 GrabRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_GrabRounding as i32, v),
288 TabRounding(v) => igPushStyleVar_Float(sys::ImGuiStyleVar_TabRounding as i32, v),
289 ButtonTextAlign(v) => {
290 igPushStyleVar_Vec2(sys::ImGuiStyleVar_ButtonTextAlign as i32, v.into())
291 }
292 SelectableTextAlign(v) => {
293 igPushStyleVar_Vec2(sys::ImGuiStyleVar_SelectableTextAlign as i32, v.into())
294 }
295 CellPadding(v) => igPushStyleVar_Vec2(sys::ImGuiStyleVar_CellPadding as i32, v.into())
296 }
297}
298
299impl<'ui> Ui<'ui> {
301 #[doc(alias = "PushItemWith")]
310 pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken {
311 unsafe { sys::igPushItemWidth(item_width) };
312 ItemWidthStackToken { _ctx: self.ctx }
313 }
314 #[doc(alias = "SetNextItemWidth")]
321 pub fn set_next_item_width(&self, item_width: f32) {
322 unsafe { sys::igSetNextItemWidth(item_width) };
323 }
324 #[doc(alias = "CalcItemWidth")]
328 pub fn calc_item_width(&self) -> f32 {
329 unsafe { sys::igCalcItemWidth() }
330 }
331
332 #[doc(alias = "PushTextWrapPos")]
340 pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken {
341 self.push_text_wrap_pos_with_pos(0.0)
342 }
343
344 #[doc(alias = "PushTextWrapPos")]
352 pub fn push_text_wrap_pos_with_pos(&self, wrap_pos_x: f32) -> TextWrapPosStackToken {
353 unsafe { sys::igPushTextWrapPos(wrap_pos_x) };
354 TextWrapPosStackToken { _ctx: self.ctx }
355 }
356
357 #[doc(alias = "PushItemFlag")]
361 pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken {
362 use self::ItemFlag::*;
363 match item_flag {
364 AllowKeyboardFocus(v) => unsafe { sys::igPushAllowKeyboardFocus(v) },
365 ButtonRepeat(v) => unsafe { sys::igPushButtonRepeat(v) },
366 }
367 ItemFlagsStackToken {
368 discriminant: mem::discriminant(&item_flag),
369 _ctx: self.ctx,
370 }
371 }
372}
373
374#[derive(Copy, Clone, Debug, PartialEq)]
376pub enum ItemFlag {
377 AllowKeyboardFocus(bool),
378 ButtonRepeat(bool),
379}
380
381pub struct ItemWidthStackToken {
382 _ctx: *const Context,
383}
384
385impl ItemWidthStackToken {
386 #[doc(alias = "PopItemWidth")]
388 pub fn pop(mut self, _: &Ui<'_>) {
389 self._ctx = ptr::null();
390 unsafe { sys::igPopItemWidth() };
391 }
392}
393
394pub struct TextWrapPosStackToken {
396 _ctx: *const Context,
397}
398
399impl TextWrapPosStackToken {
400 #[doc(alias = "PopTextWrapPos")]
402 pub fn pop(mut self, _: &Ui<'_>) {
403 self._ctx = ptr::null();
404 unsafe { sys::igPopTextWrapPos() };
405 }
406}
407
408pub struct ItemFlagsStackToken {
410 discriminant: mem::Discriminant<ItemFlag>,
411 _ctx: *const Context,
412}
413
414impl ItemFlagsStackToken {
415 #[doc(alias = "PopAllowKeyboardFocus", alias = "PopButtonRepeat")]
418 pub fn pop(mut self, _: &Ui<'_>) {
419 self._ctx = ptr::null();
420 const ALLOW_KEYBOARD_FOCUS: ItemFlag = ItemFlag::AllowKeyboardFocus(true);
421 const BUTTON_REPEAT: ItemFlag = ItemFlag::ButtonRepeat(true);
422
423 if self.discriminant == mem::discriminant(&ALLOW_KEYBOARD_FOCUS) {
424 unsafe { sys::igPopAllowKeyboardFocus() };
425 } else if self.discriminant == mem::discriminant(&BUTTON_REPEAT) {
426 unsafe { sys::igPopButtonRepeat() };
427 } else {
428 unreachable!();
429 }
430 }
431}
432
433create_token!(
434 pub struct IdStackToken<'ui>;
437
438 drop { sys::igPopID() }
440);
441
442impl IdStackToken<'_> {
443 pub fn pop(self) {
445 self.end()
446 }
447}
448
449impl<'ui> Ui<'ui> {
451 #[doc(alias = "PushId")]
456 pub fn push_id<'a, I: Into<Id<'a>>>(&self, id: I) -> IdStackToken<'ui> {
457 let id = id.into();
458
459 unsafe {
460 match id {
461 Id::Int(i) => sys::igPushID_Int(i),
462 Id::Str(s) => {
463 let start = s.as_ptr() as *const c_char;
464 let end = start.add(s.len());
465 sys::igPushID_StrStr(start, end)
466 }
467 Id::Ptr(p) => sys::igPushID_Ptr(p as *const c_void),
468 }
469 }
470 IdStackToken::new(self)
471 }
472}