mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-13 22:48:34 +00:00
Constify a large number of fns
This commit is contained in:
parent
4f1cde06f2
commit
59970d670e
@ -25,6 +25,15 @@
|
||||
- `ImColor` (which is a wrapper around `u32`) has been renamed to `ImColor32` in order to avoid confusion with the `ImColor` type from the Dear ImGui C++ code (which is a wrapper around `ImVec4`). In the future an `ImColor` type which maps more closely to the C++ one will be added.
|
||||
- Additionally, a number of constructor and accessor methods have been added to it `ImColor`, which are `const fn` where possible.
|
||||
|
||||
- The `im_str!` macro can now be used in `const` contexts (when the `format!` version is not used).
|
||||
|
||||
- `im_str!` now verifies that the parameter has no interior nuls at compile time. This can be avoided to get the old (truncating) behavior by forcing it to use the `format!`-like version, e.g. `im_str!("for_some_reason_this_should_be_truncated\0 there {}", "")`.
|
||||
- This is not recommended, and is probably not useful.
|
||||
|
||||
- Many functions are now `const fn`.
|
||||
|
||||
- A large number of small functions are now `#[inline]`, but many still aren't, so you probably will want to build with LTO for release builds if you use `imgui` heavily.
|
||||
|
||||
## [0.6.1] - 2020-12-16
|
||||
|
||||
- Support for winit 0.24.x
|
||||
|
||||
@ -13,11 +13,11 @@ pub use crate::bindings::*;
|
||||
|
||||
impl ImVec2 {
|
||||
#[inline]
|
||||
pub fn new(x: f32, y: f32) -> ImVec2 {
|
||||
pub const fn new(x: f32, y: f32) -> ImVec2 {
|
||||
ImVec2 { x, y }
|
||||
}
|
||||
#[inline]
|
||||
pub fn zero() -> ImVec2 {
|
||||
pub const fn zero() -> ImVec2 {
|
||||
ImVec2 { x: 0.0, y: 0.0 }
|
||||
}
|
||||
}
|
||||
@ -36,27 +36,27 @@ impl From<(f32, f32)> for ImVec2 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[f32; 2]> for ImVec2 {
|
||||
impl From<ImVec2> for [f32; 2] {
|
||||
#[inline]
|
||||
fn into(self) -> [f32; 2] {
|
||||
[self.x, self.y]
|
||||
fn from(v: ImVec2) -> [f32; 2] {
|
||||
[v.x, v.y]
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(f32, f32)> for ImVec2 {
|
||||
impl From<ImVec2> for (f32, f32) {
|
||||
#[inline]
|
||||
fn into(self) -> (f32, f32) {
|
||||
(self.x, self.y)
|
||||
fn from(v: ImVec2) -> (f32, f32) {
|
||||
(v.x, v.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl ImVec4 {
|
||||
#[inline]
|
||||
pub fn new(x: f32, y: f32, z: f32, w: f32) -> ImVec4 {
|
||||
pub const fn new(x: f32, y: f32, z: f32, w: f32) -> ImVec4 {
|
||||
ImVec4 { x, y, z, w }
|
||||
}
|
||||
#[inline]
|
||||
pub fn zero() -> ImVec4 {
|
||||
pub const fn zero() -> ImVec4 {
|
||||
ImVec4 {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
@ -80,17 +80,17 @@ impl From<(f32, f32, f32, f32)> for ImVec4 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[f32; 4]> for ImVec4 {
|
||||
impl From<ImVec4> for [f32; 4] {
|
||||
#[inline]
|
||||
fn into(self) -> [f32; 4] {
|
||||
[self.x, self.y, self.z, self.w]
|
||||
fn from(v: ImVec4) -> [f32; 4] {
|
||||
[v.x, v.y, v.z, v.w]
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<(f32, f32, f32, f32)> for ImVec4 {
|
||||
impl From<ImVec4> for (f32, f32, f32, f32) {
|
||||
#[inline]
|
||||
fn into(self) -> (f32, f32, f32, f32) {
|
||||
(self.x, self.y, self.z, self.w)
|
||||
fn from(v: ImVec4) -> (f32, f32, f32, f32) {
|
||||
(v.x, v.y, v.z, v.w)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ pub(crate) struct ClipboardContext {
|
||||
}
|
||||
|
||||
impl ClipboardContext {
|
||||
#[inline]
|
||||
pub fn new(backend: Box<dyn ClipboardBackend>) -> ClipboardContext {
|
||||
ClipboardContext {
|
||||
backend,
|
||||
|
||||
@ -80,6 +80,7 @@ pub enum FocusedWidget {
|
||||
}
|
||||
|
||||
impl FocusedWidget {
|
||||
#[inline]
|
||||
fn as_offset(self) -> i32 {
|
||||
match self {
|
||||
FocusedWidget::Previous => -1,
|
||||
@ -94,12 +95,14 @@ impl<'ui> Ui<'ui> {
|
||||
/// Returns the key index of the given key identifier.
|
||||
///
|
||||
/// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]`
|
||||
#[inline]
|
||||
fn key_index(&self, key: Key) -> i32 {
|
||||
unsafe { sys::igGetKeyIndex(key as i32) }
|
||||
}
|
||||
/// Returns true if the key is being held.
|
||||
///
|
||||
/// Equivalent to indexing the Io struct `keys_down` field: `ui.io().keys_down[key_index]`
|
||||
#[inline]
|
||||
pub fn is_key_down(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
unsafe { sys::igIsKeyDown(key_index) }
|
||||
@ -107,11 +110,13 @@ impl<'ui> Ui<'ui> {
|
||||
/// Returns true if the key was pressed (went from !down to down).
|
||||
///
|
||||
/// Affected by key repeat settings (`io.key_repeat_delay`, `io.key_repeat_rate`)
|
||||
#[inline]
|
||||
pub fn is_key_pressed(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
unsafe { sys::igIsKeyPressed(key_index, true) }
|
||||
}
|
||||
/// Returns true if the key was released (went from down to !down)
|
||||
#[inline]
|
||||
pub fn is_key_released(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
unsafe { sys::igIsKeyReleased(key_index) }
|
||||
@ -120,11 +125,13 @@ impl<'ui> Ui<'ui> {
|
||||
///
|
||||
/// Usually returns 0 or 1, but might be >1 if `rate` is small enough that `io.delta_time` >
|
||||
/// `rate`.
|
||||
#[inline]
|
||||
pub fn key_pressed_amount(&self, key: Key, repeat_delay: f32, rate: f32) -> u32 {
|
||||
let key_index = self.key_index(key);
|
||||
unsafe { sys::igGetKeyPressedAmount(key_index, repeat_delay, rate) as u32 }
|
||||
}
|
||||
/// Focuses keyboard on a widget relative to current position
|
||||
#[inline]
|
||||
pub fn set_keyboard_focus_here(&self, target_widget: FocusedWidget) {
|
||||
unsafe {
|
||||
sys::igSetKeyboardFocusHere(target_widget.as_offset());
|
||||
|
||||
@ -12,6 +12,7 @@ pub struct ImVector<T> {
|
||||
}
|
||||
|
||||
impl<T> ImVector<T> {
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe { slice::from_raw_parts(self.data, self.size as usize) }
|
||||
}
|
||||
@ -71,6 +72,7 @@ pub unsafe trait RawCast<T>: Sized {
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the cast is valid.
|
||||
#[inline]
|
||||
unsafe fn from_raw(raw: &T) -> &Self {
|
||||
&*(raw as *const _ as *const Self)
|
||||
}
|
||||
@ -79,6 +81,7 @@ pub unsafe trait RawCast<T>: Sized {
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the cast is valid.
|
||||
#[inline]
|
||||
unsafe fn from_raw_mut(raw: &mut T) -> &mut Self {
|
||||
&mut *(raw as *mut _ as *mut Self)
|
||||
}
|
||||
@ -87,6 +90,7 @@ pub unsafe trait RawCast<T>: Sized {
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the cast is valid.
|
||||
#[inline]
|
||||
unsafe fn raw(&self) -> &T {
|
||||
&*(self as *const _ as *const T)
|
||||
}
|
||||
@ -95,6 +99,7 @@ pub unsafe trait RawCast<T>: Sized {
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the cast is valid.
|
||||
#[inline]
|
||||
unsafe fn raw_mut(&mut self) -> &mut T {
|
||||
&mut *(self as *mut _ as *mut T)
|
||||
}
|
||||
@ -182,27 +187,33 @@ pub trait InclusiveRangeBounds<T: Copy> {
|
||||
}
|
||||
|
||||
impl<T: Copy> InclusiveRangeBounds<T> for RangeFrom<T> {
|
||||
#[inline]
|
||||
fn start_bound(&self) -> Option<&T> {
|
||||
Some(&self.start)
|
||||
}
|
||||
#[inline]
|
||||
fn end_bound(&self) -> Option<&T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> InclusiveRangeBounds<T> for RangeInclusive<T> {
|
||||
#[inline]
|
||||
fn start_bound(&self) -> Option<&T> {
|
||||
Some(self.start())
|
||||
}
|
||||
#[inline]
|
||||
fn end_bound(&self) -> Option<&T> {
|
||||
Some(self.end())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> InclusiveRangeBounds<T> for RangeToInclusive<T> {
|
||||
#[inline]
|
||||
fn start_bound(&self) -> Option<&T> {
|
||||
None
|
||||
}
|
||||
#[inline]
|
||||
fn end_bound(&self) -> Option<&T> {
|
||||
Some(&self.end)
|
||||
}
|
||||
|
||||
@ -50,6 +50,9 @@ pub use self::window::child_window::*;
|
||||
pub use self::window::*;
|
||||
use internal::RawCast;
|
||||
|
||||
#[macro_use]
|
||||
mod string;
|
||||
|
||||
mod clipboard;
|
||||
pub mod color;
|
||||
mod columns;
|
||||
@ -68,7 +71,6 @@ mod plotlines;
|
||||
mod popup_modal;
|
||||
mod render;
|
||||
mod stacks;
|
||||
mod string;
|
||||
mod style;
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
@ -76,6 +78,11 @@ mod utils;
|
||||
mod widget;
|
||||
mod window;
|
||||
|
||||
// Used by macros. Underscores are just to make it clear it's not part of the
|
||||
// public API.
|
||||
#[doc(hidden)]
|
||||
pub use core as __core;
|
||||
|
||||
/// Returns the underlying Dear ImGui library version
|
||||
pub fn dear_imgui_version() -> &'static str {
|
||||
unsafe {
|
||||
@ -199,24 +206,28 @@ pub enum Id<'a> {
|
||||
}
|
||||
|
||||
impl From<i32> for Id<'static> {
|
||||
#[inline]
|
||||
fn from(i: i32) -> Self {
|
||||
Id::Int(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + AsRef<str>> From<&'a T> for Id<'a> {
|
||||
#[inline]
|
||||
fn from(s: &'a T) -> Self {
|
||||
Id::Str(s.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*const T> for Id<'static> {
|
||||
#[inline]
|
||||
fn from(p: *const T) -> Self {
|
||||
Id::Ptr(p as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*mut T> for Id<'static> {
|
||||
#[inline]
|
||||
fn from(p: *mut T) -> Self {
|
||||
Id::Ptr(p as *const T as *const c_void)
|
||||
}
|
||||
|
||||
@ -10,14 +10,14 @@ pub struct ListClipper {
|
||||
}
|
||||
|
||||
impl ListClipper {
|
||||
pub fn new(items_count: i32) -> Self {
|
||||
pub const fn new(items_count: i32) -> Self {
|
||||
ListClipper {
|
||||
items_count,
|
||||
items_height: -1.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn items_height(mut self, items_height: f32) -> Self {
|
||||
pub const fn items_height(mut self, items_height: f32) -> Self {
|
||||
self.items_height = items_height;
|
||||
self
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct PlotHistogram<'ui, 'p> {
|
||||
}
|
||||
|
||||
impl<'ui, 'p> PlotHistogram<'ui, 'p> {
|
||||
pub fn new(_: &Ui<'ui>, label: &'p ImStr, values: &'p [f32]) -> Self {
|
||||
pub const fn new(_: &Ui<'ui>, label: &'p ImStr, values: &'p [f32]) -> Self {
|
||||
PlotHistogram {
|
||||
label,
|
||||
values,
|
||||
@ -31,31 +31,31 @@ impl<'ui, 'p> PlotHistogram<'ui, 'p> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn values_offset(mut self, values_offset: usize) -> Self {
|
||||
pub const fn values_offset(mut self, values_offset: usize) -> Self {
|
||||
self.values_offset = values_offset;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
|
||||
pub const fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
|
||||
self.overlay_text = Some(overlay_text);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_min(mut self, scale_min: f32) -> Self {
|
||||
pub const fn scale_min(mut self, scale_min: f32) -> Self {
|
||||
self.scale_min = scale_min;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_max(mut self, scale_max: f32) -> Self {
|
||||
pub const fn scale_max(mut self, scale_max: f32) -> Self {
|
||||
self.scale_max = scale_max;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
|
||||
pub const fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
|
||||
self.graph_size = graph_size;
|
||||
self
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct PlotLines<'ui, 'p> {
|
||||
}
|
||||
|
||||
impl<'ui, 'p> PlotLines<'ui, 'p> {
|
||||
pub fn new(_: &Ui<'ui>, label: &'p ImStr, values: &'p [f32]) -> Self {
|
||||
pub const fn new(_: &Ui<'ui>, label: &'p ImStr, values: &'p [f32]) -> Self {
|
||||
PlotLines {
|
||||
label,
|
||||
values,
|
||||
@ -31,31 +31,31 @@ impl<'ui, 'p> PlotLines<'ui, 'p> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn values_offset(mut self, values_offset: usize) -> Self {
|
||||
pub const fn values_offset(mut self, values_offset: usize) -> Self {
|
||||
self.values_offset = values_offset;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
|
||||
pub const fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
|
||||
self.overlay_text = Some(overlay_text);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_min(mut self, scale_min: f32) -> Self {
|
||||
pub const fn scale_min(mut self, scale_min: f32) -> Self {
|
||||
self.scale_min = scale_min;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scale_max(mut self, scale_max: f32) -> Self {
|
||||
pub const fn scale_max(mut self, scale_max: f32) -> Self {
|
||||
self.scale_max = scale_max;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
|
||||
pub const fn graph_size(mut self, graph_size: [f32; 2]) -> Self {
|
||||
self.graph_size = graph_size;
|
||||
self
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ unsafe impl RawCast<sys::ImDrawData> for DrawData {}
|
||||
|
||||
impl DrawData {
|
||||
/// Returns an iterator over the draw lists included in the draw data.
|
||||
#[inline]
|
||||
pub fn draw_lists(&self) -> DrawListIterator {
|
||||
unsafe {
|
||||
DrawListIterator {
|
||||
@ -44,10 +45,12 @@ impl DrawData {
|
||||
}
|
||||
}
|
||||
/// Returns the number of draw lists included in the draw data.
|
||||
#[inline]
|
||||
pub fn draw_lists_count(&self) -> usize {
|
||||
use std::convert::TryInto;
|
||||
self.cmd_lists_count.try_into().unwrap()
|
||||
}
|
||||
#[inline]
|
||||
pub(crate) unsafe fn cmd_lists(&self) -> &[*const DrawList] {
|
||||
slice::from_raw_parts(
|
||||
self.cmd_lists as *const *const DrawList,
|
||||
@ -124,21 +127,25 @@ pub struct DrawList(sys::ImDrawList);
|
||||
|
||||
impl RawWrapper for DrawList {
|
||||
type Raw = sys::ImDrawList;
|
||||
#[inline]
|
||||
unsafe fn raw(&self) -> &sys::ImDrawList {
|
||||
&self.0
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn raw_mut(&mut self) -> &mut sys::ImDrawList {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DrawList {
|
||||
#[inline]
|
||||
pub(crate) unsafe fn cmd_buffer(&self) -> &[sys::ImDrawCmd] {
|
||||
slice::from_raw_parts(
|
||||
self.0.CmdBuffer.Data as *const sys::ImDrawCmd,
|
||||
self.0.CmdBuffer.Size as usize,
|
||||
)
|
||||
}
|
||||
#[inline]
|
||||
pub fn idx_buffer(&self) -> &[DrawIdx] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
@ -147,6 +154,7 @@ impl DrawList {
|
||||
)
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn vtx_buffer(&self) -> &[DrawVert] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
@ -170,6 +178,7 @@ impl DrawList {
|
||||
slice::from_raw_parts(self.0.VtxBuffer.Data.cast(), self.0.VtxBuffer.Size as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn commands(&self) -> DrawCmdIterator {
|
||||
unsafe {
|
||||
DrawCmdIterator {
|
||||
@ -186,6 +195,7 @@ pub struct DrawCmdIterator<'a> {
|
||||
impl<'a> Iterator for DrawCmdIterator<'a> {
|
||||
type Item = DrawCmd;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|cmd| {
|
||||
let cmd_params = DrawCmdParams {
|
||||
|
||||
@ -7,29 +7,34 @@ pub struct TextureId(usize);
|
||||
|
||||
impl TextureId {
|
||||
/// Creates a new texture id with the given identifier.
|
||||
pub fn new(id: usize) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(id: usize) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
|
||||
/// Returns the id of the TextureId.
|
||||
pub fn id(self) -> usize {
|
||||
#[inline]
|
||||
pub const fn id(self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for TextureId {
|
||||
#[inline]
|
||||
fn from(id: usize) -> Self {
|
||||
TextureId(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*const T> for TextureId {
|
||||
#[inline]
|
||||
fn from(ptr: *const T) -> Self {
|
||||
TextureId(ptr as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*mut T> for TextureId {
|
||||
#[inline]
|
||||
fn from(ptr: *mut T) -> Self {
|
||||
TextureId(ptr as usize)
|
||||
}
|
||||
@ -56,6 +61,8 @@ pub struct Textures<T> {
|
||||
}
|
||||
|
||||
impl<T> Textures<T> {
|
||||
// TODO: hasher like rustc_hash::FxHashMap or something would let this be
|
||||
// `const fn`
|
||||
pub fn new() -> Self {
|
||||
Textures {
|
||||
textures: HashMap::new(),
|
||||
|
||||
@ -7,19 +7,34 @@ use std::str;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! im_str {
|
||||
($e:tt) => ({
|
||||
unsafe {
|
||||
$crate::ImStr::from_utf8_with_nul_unchecked(concat!($e, "\0").as_bytes())
|
||||
($e:literal $(,)?) => {{
|
||||
const __INPUT: &str = concat!($e, "\0");
|
||||
{
|
||||
// Trigger a compile error if there's an interior NUL character.
|
||||
const _CHECK_NUL: [(); 0] = [(); {
|
||||
let bytes = __INPUT.as_bytes();
|
||||
let mut i = 0;
|
||||
let mut found_nul = 0;
|
||||
while i < bytes.len() - 1 && found_nul == 0 {
|
||||
if bytes[i] == 0 {
|
||||
found_nul = 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
found_nul
|
||||
}];
|
||||
const RESULT: &'static $crate::ImStr = unsafe {
|
||||
$crate::__core::mem::transmute::<&'static [u8], &'static $crate::ImStr>(__INPUT.as_bytes())
|
||||
};
|
||||
RESULT
|
||||
}
|
||||
}};
|
||||
($e:literal, $($arg:tt)+) => ({
|
||||
$crate::ImString::new(format!($e, $($arg)*))
|
||||
});
|
||||
($e:tt, $($arg:tt)*) => ({
|
||||
unsafe {
|
||||
$crate::ImString::from_utf8_with_nul_unchecked(format!(concat!($e, "\0"), $($arg)*).into_bytes())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// A UTF-8 encoded, growable, implicitly null-terminated string.
|
||||
/// A UTF-8 encoded, growable, implicitly nul-terminated string.
|
||||
#[derive(Clone, Hash, Ord, Eq, PartialOrd, PartialEq)]
|
||||
pub struct ImString(pub(crate) Vec<u8>);
|
||||
|
||||
@ -32,42 +47,54 @@ impl ImString {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new empty `ImString` with a particular capacity
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: usize) -> ImString {
|
||||
let mut v = Vec::with_capacity(capacity + 1);
|
||||
v.push(b'\0');
|
||||
ImString(v)
|
||||
}
|
||||
|
||||
/// Converts a vector of bytes to a `ImString` without checking that the string contains valid
|
||||
/// UTF-8
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the vector contains valid UTF-8 and no null terminator.
|
||||
#[inline]
|
||||
pub unsafe fn from_utf8_unchecked(mut v: Vec<u8>) -> ImString {
|
||||
v.push(b'\0');
|
||||
ImString(v)
|
||||
}
|
||||
|
||||
/// Converts a vector of bytes to a `ImString` without checking that the string contains valid
|
||||
/// UTF-8
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the vector contains valid UTF-8 and a null terminator.
|
||||
#[inline]
|
||||
pub unsafe fn from_utf8_with_nul_unchecked(v: Vec<u8>) -> ImString {
|
||||
ImString(v)
|
||||
}
|
||||
|
||||
/// Truncates this `ImString`, removing all contents
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear();
|
||||
self.0.push(b'\0');
|
||||
}
|
||||
|
||||
/// Appends the given character to the end of this `ImString`
|
||||
#[inline]
|
||||
pub fn push(&mut self, ch: char) {
|
||||
let mut buf = [0; 4];
|
||||
self.push_str(ch.encode_utf8(&mut buf));
|
||||
}
|
||||
|
||||
/// Appends a given string slice to the end of this `ImString`
|
||||
#[inline]
|
||||
pub fn push_str(&mut self, string: &str) {
|
||||
self.0.pop();
|
||||
self.0.extend(string.bytes());
|
||||
@ -76,14 +103,19 @@ impl ImString {
|
||||
self.refresh_len();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the capacity of this `ImString` in bytes
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.0.capacity() - 1
|
||||
}
|
||||
|
||||
/// Returns the capacity of this `ImString` in bytes, including the implicit null byte
|
||||
#[inline]
|
||||
pub fn capacity_with_nul(&self) -> usize {
|
||||
self.0.capacity()
|
||||
}
|
||||
|
||||
/// Ensures that the capacity of this `ImString` is at least `additional` bytes larger than the
|
||||
/// current length.
|
||||
///
|
||||
@ -91,21 +123,27 @@ impl ImString {
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
self.0.reserve(additional);
|
||||
}
|
||||
|
||||
/// Ensures that the capacity of this `ImString` is at least `additional` bytes larger than the
|
||||
/// current length
|
||||
pub fn reserve_exact(&mut self, additional: usize) {
|
||||
self.0.reserve_exact(additional);
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the underlying buffer
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const c_char {
|
||||
self.0.as_ptr() as *const c_char
|
||||
}
|
||||
|
||||
/// Returns a raw mutable pointer to the underlying buffer.
|
||||
///
|
||||
/// If the underlying data is modified, `refresh_len` *must* be called afterwards.
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut c_char {
|
||||
self.0.as_mut_ptr() as *mut c_char
|
||||
}
|
||||
|
||||
/// Updates the underlying buffer length based on the current contents.
|
||||
///
|
||||
/// This function *must* be called if the underlying data is modified via a pointer
|
||||
@ -115,6 +153,7 @@ impl ImString {
|
||||
///
|
||||
/// It is up to the caller to guarantee the this ImString contains valid UTF-8 and a null
|
||||
/// terminator.
|
||||
#[inline]
|
||||
pub unsafe fn refresh_len(&mut self) {
|
||||
let len = CStr::from_ptr(self.0.as_ptr() as *const c_char)
|
||||
.to_bytes_with_nul()
|
||||
@ -124,54 +163,63 @@ impl ImString {
|
||||
}
|
||||
|
||||
impl<'a> Default for ImString {
|
||||
#[inline]
|
||||
fn default() -> ImString {
|
||||
ImString(vec![b'\0'])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ImString {
|
||||
#[inline]
|
||||
fn from(s: String) -> ImString {
|
||||
ImString::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ImString> for Cow<'a, ImStr> {
|
||||
#[inline]
|
||||
fn from(s: ImString) -> Cow<'a, ImStr> {
|
||||
Cow::Owned(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ImString> for Cow<'a, ImStr> {
|
||||
#[inline]
|
||||
fn from(s: &'a ImString) -> Cow<'a, ImStr> {
|
||||
Cow::Borrowed(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + AsRef<ImStr>> From<&'a T> for ImString {
|
||||
#[inline]
|
||||
fn from(s: &'a T) -> ImString {
|
||||
s.as_ref().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<ImStr> for ImString {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &ImStr {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<ImStr> for ImString {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &ImStr {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ImString {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.to_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for ImString {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &str {
|
||||
self.to_str()
|
||||
}
|
||||
@ -179,18 +227,21 @@ impl Borrow<str> for ImString {
|
||||
|
||||
impl Index<RangeFull> for ImString {
|
||||
type Output = ImStr;
|
||||
#[inline]
|
||||
fn index(&self, _index: RangeFull) -> &ImStr {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ImString {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(self.to_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ImString {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(self.to_str(), f)
|
||||
}
|
||||
@ -198,6 +249,7 @@ impl fmt::Display for ImString {
|
||||
|
||||
impl Deref for ImString {
|
||||
type Target = ImStr;
|
||||
#[inline]
|
||||
fn deref(&self) -> &ImStr {
|
||||
// as_ptr() is used, because we need to look at the bytes to figure out the length
|
||||
// self.0.len() is incorrect, because there might be more than one nul byte in the end, or
|
||||
@ -222,11 +274,13 @@ impl fmt::Write for ImString {
|
||||
}
|
||||
}
|
||||
|
||||
/// A UTF-8 encoded, implicitly null-terminated string slice.
|
||||
/// A UTF-8 encoded, implicitly nul-terminated string slice.
|
||||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ImStr(CStr);
|
||||
#[repr(transparent)]
|
||||
pub struct ImStr([u8]);
|
||||
|
||||
impl<'a> Default for &'a ImStr {
|
||||
#[inline]
|
||||
fn default() -> &'a ImStr {
|
||||
static SLICE: &[u8] = &[0];
|
||||
unsafe { ImStr::from_utf8_with_nul_unchecked(SLICE) }
|
||||
@ -234,12 +288,14 @@ impl<'a> Default for &'a ImStr {
|
||||
}
|
||||
|
||||
impl fmt::Debug for ImStr {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ImStr {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(self.to_str(), f)
|
||||
}
|
||||
@ -252,60 +308,91 @@ impl ImStr {
|
||||
///
|
||||
/// It is up to the caller to guarantee the pointer is not null and it points to a
|
||||
/// null-terminated UTF-8 string valid for the duration of the arbitrary lifetime 'a.
|
||||
#[inline]
|
||||
pub unsafe fn from_ptr_unchecked<'a>(ptr: *const c_char) -> &'a ImStr {
|
||||
ImStr::from_cstr_unchecked(CStr::from_ptr(ptr))
|
||||
}
|
||||
|
||||
/// Converts a slice of bytes to an imgui-rs string slice without checking for valid UTF-8 or
|
||||
/// null termination.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the slice contains valid UTF-8 and a null terminator.
|
||||
#[inline]
|
||||
pub unsafe fn from_utf8_with_nul_unchecked(bytes: &[u8]) -> &ImStr {
|
||||
&*(bytes as *const [u8] as *const ImStr)
|
||||
}
|
||||
|
||||
/// Converts a CStr reference to an imgui-rs string slice without checking for valid UTF-8.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee the CStr reference contains valid UTF-8.
|
||||
#[inline]
|
||||
pub unsafe fn from_cstr_unchecked(value: &CStr) -> &ImStr {
|
||||
&*(value as *const CStr as *const ImStr)
|
||||
&*(value.to_bytes_with_nul() as *const [u8] as *const ImStr)
|
||||
}
|
||||
|
||||
/// Converts an imgui-rs string slice to a raw pointer
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const c_char {
|
||||
self.0.as_ptr()
|
||||
self.0.as_ptr() as *const c_char
|
||||
}
|
||||
|
||||
/// Converts an imgui-rs string slice to a normal string slice
|
||||
#[inline]
|
||||
pub fn to_str(&self) -> &str {
|
||||
// CStr::to_bytes does *not* include the null terminator
|
||||
unsafe { str::from_utf8_unchecked(self.0.to_bytes()) }
|
||||
self.sanity_check();
|
||||
unsafe { str::from_utf8_unchecked(&self.0[..(self.0.len() - 1)]) }
|
||||
}
|
||||
|
||||
/// Returns true if the imgui-rs string slice is empty
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.to_bytes().is_empty()
|
||||
debug_assert!(self.0.len() != 0);
|
||||
self.0.len() == 1
|
||||
}
|
||||
|
||||
// TODO: if this is too slow, avoid the UTF8 validation except if we'd
|
||||
// already be doing O(n) stuff.
|
||||
#[inline]
|
||||
fn sanity_check(&self) {
|
||||
debug_assert!(
|
||||
str::from_utf8(&self.0).is_ok()
|
||||
&& !self.0.is_empty()
|
||||
&& !self.0[..(self.0.len() - 1)].contains(&0u8)
|
||||
&& self.0[self.0.len() - 1] == 0,
|
||||
"bad ImStr: {:?}",
|
||||
&self.0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<CStr> for ImStr {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &CStr {
|
||||
&self.0
|
||||
// Safety: our safety requirements are a superset of CStr's, so this is fine
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(&self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<ImStr> for ImStr {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &ImStr {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ImStr {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self.to_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ImStr> for Cow<'a, ImStr> {
|
||||
#[inline]
|
||||
fn from(s: &'a ImStr) -> Cow<'a, ImStr> {
|
||||
Cow::Borrowed(s)
|
||||
}
|
||||
@ -313,8 +400,10 @@ impl<'a> From<&'a ImStr> for Cow<'a, ImStr> {
|
||||
|
||||
impl ToOwned for ImStr {
|
||||
type Owned = ImString;
|
||||
#[inline]
|
||||
fn to_owned(&self) -> ImString {
|
||||
ImString(self.0.to_owned().into_bytes())
|
||||
self.sanity_check();
|
||||
ImString(self.0.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -182,12 +182,14 @@ impl Style {
|
||||
|
||||
impl Index<StyleColor> for Style {
|
||||
type Output = [f32; 4];
|
||||
#[inline]
|
||||
fn index(&self, index: StyleColor) -> &[f32; 4] {
|
||||
&self.colors[index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<StyleColor> for Style {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: StyleColor) -> &mut [f32; 4] {
|
||||
&mut self.colors[index as usize]
|
||||
}
|
||||
|
||||
@ -66,25 +66,28 @@ pub struct ComboBox<'a> {
|
||||
|
||||
impl<'a> ComboBox<'a> {
|
||||
/// Constructs a new combo box builder.
|
||||
pub fn new(label: &'a ImStr) -> ComboBox<'a> {
|
||||
pub const fn new(label: &'a ImStr) -> ComboBox<'a> {
|
||||
ComboBox {
|
||||
label,
|
||||
preview_value: None,
|
||||
flags: ComboBoxFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the preview value displayed in the preview box (if visible).
|
||||
#[inline]
|
||||
pub fn preview_value(mut self, preview_value: &'a ImStr) -> Self {
|
||||
pub const fn preview_value(mut self, preview_value: &'a ImStr) -> Self {
|
||||
self.preview_value = Some(preview_value);
|
||||
self
|
||||
}
|
||||
|
||||
/// Replaces all current settings with the given flags.
|
||||
#[inline]
|
||||
pub fn flags(mut self, flags: ComboBoxFlags) -> Self {
|
||||
pub const fn flags(mut self, flags: ComboBoxFlags) -> Self {
|
||||
self.flags = flags;
|
||||
self
|
||||
}
|
||||
|
||||
/// Enables/disables aligning the combo box popup toward the left.
|
||||
///
|
||||
/// Disabled by default.
|
||||
@ -94,6 +97,7 @@ impl<'a> ComboBox<'a> {
|
||||
.set(ComboBoxFlags::POPUP_ALIGN_LEFT, popup_align_left);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the combo box height.
|
||||
///
|
||||
/// Default: `ComboBoxHeight::Regular`
|
||||
@ -113,6 +117,7 @@ impl<'a> ComboBox<'a> {
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the combo box preview mode.
|
||||
///
|
||||
/// Default: `ComboBoxPreviewMode::Full`
|
||||
@ -128,6 +133,7 @@ impl<'a> ComboBox<'a> {
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates a combo box and starts appending to it.
|
||||
///
|
||||
/// Returns `Some(ComboBoxToken)` if the combo box is open. After content has been
|
||||
|
||||
@ -18,7 +18,7 @@ pub struct Image {
|
||||
|
||||
impl Image {
|
||||
/// Creates a new image builder with the given texture and size
|
||||
pub fn new(texture_id: TextureId, size: [f32; 2]) -> Image {
|
||||
pub const fn new(texture_id: TextureId, size: [f32; 2]) -> Image {
|
||||
Image {
|
||||
texture_id,
|
||||
size,
|
||||
@ -29,27 +29,27 @@ impl Image {
|
||||
}
|
||||
}
|
||||
/// Sets the image size
|
||||
pub fn size(mut self, size: [f32; 2]) -> Self {
|
||||
pub const fn size(mut self, size: [f32; 2]) -> Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
/// Sets uv0 (default `[0.0, 0.0]`)
|
||||
pub fn uv0(mut self, uv0: [f32; 2]) -> Self {
|
||||
pub const fn uv0(mut self, uv0: [f32; 2]) -> Self {
|
||||
self.uv0 = uv0;
|
||||
self
|
||||
}
|
||||
/// Sets uv1 (default `[1.0, 1.0]`)
|
||||
pub fn uv1(mut self, uv1: [f32; 2]) -> Self {
|
||||
pub const fn uv1(mut self, uv1: [f32; 2]) -> Self {
|
||||
self.uv1 = uv1;
|
||||
self
|
||||
}
|
||||
/// Sets the tint color (default: no tint color)
|
||||
pub fn tint_col(mut self, tint_col: [f32; 4]) -> Self {
|
||||
pub const fn tint_col(mut self, tint_col: [f32; 4]) -> Self {
|
||||
self.tint_col = tint_col;
|
||||
self
|
||||
}
|
||||
/// Sets the border color (default: no border)
|
||||
pub fn border_col(mut self, border_col: [f32; 4]) -> Self {
|
||||
pub const fn border_col(mut self, border_col: [f32; 4]) -> Self {
|
||||
self.border_col = border_col;
|
||||
self
|
||||
}
|
||||
|
||||
@ -9,9 +9,7 @@ use crate::Ui;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Size {
|
||||
Vec {
|
||||
size: sys::ImVec2,
|
||||
},
|
||||
Vec(sys::ImVec2),
|
||||
Items {
|
||||
items_count: i32,
|
||||
height_in_items: i32,
|
||||
@ -27,12 +25,10 @@ pub struct ListBox<'a> {
|
||||
|
||||
impl<'a> ListBox<'a> {
|
||||
/// Constructs a new list box builder.
|
||||
pub fn new(label: &'a ImStr) -> ListBox<'a> {
|
||||
pub const fn new(label: &'a ImStr) -> ListBox<'a> {
|
||||
ListBox {
|
||||
label,
|
||||
size: Size::Vec {
|
||||
size: [0.0, 0.0].into(),
|
||||
},
|
||||
size: Size::Vec(sys::ImVec2::zero()),
|
||||
}
|
||||
}
|
||||
/// Sets the list box size based on the number of items that you want to make visible
|
||||
@ -40,13 +36,14 @@ impl<'a> ListBox<'a> {
|
||||
/// We add +25% worth of item height to allow the user to see at a glance if there are more items up/down, without looking at the scrollbar.
|
||||
/// We don't add this extra bit if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size.
|
||||
#[inline]
|
||||
pub fn calculate_size(mut self, items_count: i32, height_in_items: i32) -> Self {
|
||||
pub const fn calculate_size(mut self, items_count: i32, height_in_items: i32) -> Self {
|
||||
self.size = Size::Items {
|
||||
items_count,
|
||||
height_in_items,
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the list box size based on the given width and height
|
||||
/// If width or height are 0 or smaller, a default value is calculated
|
||||
/// Helper to calculate the size of a listbox and display a label on the right.
|
||||
@ -54,8 +51,8 @@ impl<'a> ListBox<'a> {
|
||||
///
|
||||
/// Default: [0.0, 0.0], in which case the combobox calculates a sensible width and height
|
||||
#[inline]
|
||||
pub fn size(mut self, size: [f32; 2]) -> Self {
|
||||
self.size = Size::Vec { size: size.into() };
|
||||
pub const fn size(mut self, size: [f32; 2]) -> Self {
|
||||
self.size = Size::Vec(sys::ImVec2::new(size[0], size[1]));
|
||||
self
|
||||
}
|
||||
/// Creates a list box and starts appending to it.
|
||||
@ -68,7 +65,7 @@ impl<'a> ListBox<'a> {
|
||||
pub fn begin(self, ui: &Ui) -> Option<ListBoxToken> {
|
||||
let should_render = unsafe {
|
||||
match self.size {
|
||||
Size::Vec { size } => sys::igListBoxHeaderVec2(self.label.as_ptr(), size),
|
||||
Size::Vec(size) => sys::igListBoxHeaderVec2(self.label.as_ptr(), size),
|
||||
Size::Items {
|
||||
items_count,
|
||||
height_in_items,
|
||||
|
||||
@ -31,16 +31,18 @@ impl<'a> ProgressBar<'a> {
|
||||
///
|
||||
/// The progress bar will be automatically sized to fill the entire width of the window if no
|
||||
/// custom size is specified.
|
||||
pub fn new(fraction: f32) -> ProgressBar<'a> {
|
||||
#[inline]
|
||||
pub const fn new(fraction: f32) -> ProgressBar<'a> {
|
||||
ProgressBar {
|
||||
fraction,
|
||||
size: [-1.0, 0.0],
|
||||
overlay_text: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets an optional text that will be drawn over the progress bar.
|
||||
#[inline]
|
||||
pub fn overlay_text(mut self, overlay_text: &'a ImStr) -> ProgressBar {
|
||||
pub const fn overlay_text(mut self, overlay_text: &'a ImStr) -> ProgressBar {
|
||||
self.overlay_text = Some(overlay_text);
|
||||
self
|
||||
}
|
||||
@ -50,10 +52,11 @@ impl<'a> ProgressBar<'a> {
|
||||
/// Negative values will automatically align to the end of the axis, zero will let the progress
|
||||
/// bar choose a size, and positive values will use the given size.
|
||||
#[inline]
|
||||
pub fn size(mut self, size: [f32; 2]) -> Self {
|
||||
pub const fn size(mut self, size: [f32; 2]) -> Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the progress bar
|
||||
pub fn build(self, _: &Ui) {
|
||||
unsafe {
|
||||
|
||||
@ -33,7 +33,8 @@ pub struct Selectable<'a> {
|
||||
|
||||
impl<'a> Selectable<'a> {
|
||||
/// Constructs a new selectable builder.
|
||||
pub fn new(label: &ImStr) -> Selectable {
|
||||
#[inline]
|
||||
pub const fn new(label: &ImStr) -> Selectable {
|
||||
Selectable {
|
||||
label,
|
||||
selected: false,
|
||||
|
||||
@ -182,7 +182,6 @@ pub struct AngleSlider<'a> {
|
||||
impl<'a> AngleSlider<'a> {
|
||||
/// Constructs a new angle slider builder.
|
||||
pub fn new(label: &ImStr) -> AngleSlider {
|
||||
use crate::im_str;
|
||||
AngleSlider {
|
||||
label,
|
||||
min_degrees: -360.0,
|
||||
|
||||
@ -63,7 +63,8 @@ pub struct TabBar<'a> {
|
||||
}
|
||||
|
||||
impl<'a> TabBar<'a> {
|
||||
pub fn new(id: &'a ImStr) -> Self {
|
||||
#[inline]
|
||||
pub const fn new(id: &'a ImStr) -> Self {
|
||||
Self {
|
||||
id,
|
||||
flags: TabBarFlags::empty(),
|
||||
|
||||
@ -70,18 +70,21 @@ pub enum TreeNodeId<'a> {
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized + AsRef<ImStr>> From<&'a T> for TreeNodeId<'a> {
|
||||
#[inline]
|
||||
fn from(s: &'a T) -> Self {
|
||||
TreeNodeId::Str(s.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*const T> for TreeNodeId<'static> {
|
||||
#[inline]
|
||||
fn from(p: *const T) -> Self {
|
||||
TreeNodeId::Ptr(p as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<*mut T> for TreeNodeId<'static> {
|
||||
#[inline]
|
||||
fn from(p: *mut T) -> Self {
|
||||
TreeNodeId::Ptr(p as *const T as *const c_void)
|
||||
}
|
||||
@ -289,6 +292,7 @@ pub struct TreeNodeToken {
|
||||
|
||||
impl TreeNodeToken {
|
||||
/// Pops a tree node
|
||||
#[inline]
|
||||
pub fn pop(mut self, _: &Ui) {
|
||||
if !self.ctx.is_null() {
|
||||
self.ctx = ptr::null();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user