mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-27 21:38:34 +00:00
Merge pull request #539 from sanbox-irl/simplify-ui-lifetime
Remove the lifetime from Ui
This commit is contained in:
commit
b798342157
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
- BREAKING: Removed `push_style_colors` and `push_style_vars`. Instead, use `push_style_color` in a loop. This was deprecated in `0.7.0` and should have been removed in `0.8.0`. This also removes their associated tokens.
|
- BREAKING: Removed `push_style_colors` and `push_style_vars`. Instead, use `push_style_color` in a loop. This was deprecated in `0.7.0` and should have been removed in `0.8.0`. This also removes their associated tokens.
|
||||||
|
|
||||||
|
- BREAKING: Ui now does not have a lifetime associated with it, but is only ever given to users in the form of `&mut Ui`. Additionally, the `render` function has been moved to the `Context` instead of `Ui`.
|
||||||
|
|
||||||
|
- BREAKING: `SharedFontAtlas` now uses `UnsafeCell` rather than `Rc<RefCell>` as its wrapper -- this simplifies the codebase and more accurately reflects how we expect `SharedFontAtlas` to be used (ie, you're probably going to set it up once, and then give it around, rather than constantly edit it). `SharedFontAtlas` users, if this change is very bad for you, please let us know with issues!
|
||||||
|
|
||||||
## [0.8.0] - 2021-09-17
|
## [0.8.0] - 2021-09-17
|
||||||
|
|
||||||
Welcome to the `0.8.0` update. This is one of the largest updates imgui-rs has ever seen; it will generate errors in a `0.7` project, but hopefully it should be both quick to fix, and enjoyable to update. See our [release page](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.8.0) for more information and a list of contributors to this cycle. Thank you to everyone who uses `imgui-rs`, files issues, and spend their time and effort to PR new changes into the codebase. Because of all that effort, this is by far the best `imgui-rs` has looked!
|
Welcome to the `0.8.0` update. This is one of the largest updates imgui-rs has ever seen; it will generate errors in a `0.7` project, but hopefully it should be both quick to fix, and enjoyable to update. See our [release page](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.8.0) for more information and a list of contributors to this cycle. Thank you to everyone who uses `imgui-rs`, files issues, and spend their time and effort to PR new changes into the codebase. Because of all that effort, this is by far the best `imgui-rs` has looked!
|
||||||
|
|||||||
@ -120,8 +120,8 @@ impl System {
|
|||||||
let gl_window = display.gl_window();
|
let gl_window = display.gl_window();
|
||||||
let mut target = display.draw();
|
let mut target = display.draw();
|
||||||
target.clear_color_srgb(1.0, 1.0, 1.0, 1.0);
|
target.clear_color_srgb(1.0, 1.0, 1.0, 1.0);
|
||||||
platform.prepare_render(&ui, gl_window.window());
|
platform.prepare_render(ui, gl_window.window());
|
||||||
let draw_data = ui.render();
|
let draw_data = imgui.render();
|
||||||
renderer
|
renderer
|
||||||
.render(&mut target, draw_data)
|
.render(&mut target, draw_data)
|
||||||
.expect("Rendering failed");
|
.expect("Rendering failed");
|
||||||
|
|||||||
@ -330,7 +330,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
|
|||||||
window = window.opened(opened)
|
window = window.opened(opened)
|
||||||
}
|
}
|
||||||
window.build(|| {
|
window.build(|| {
|
||||||
ui.push_item_width(-140.0);
|
let _w = ui.push_item_width(-140.0);
|
||||||
ui.text(format!("dear imgui says hello. ({})", imgui::dear_imgui_version()));
|
ui.text(format!("dear imgui says hello. ({})", imgui::dear_imgui_version()));
|
||||||
if let Some(menu_bar) = ui.begin_menu_bar() {
|
if let Some(menu_bar) = ui.begin_menu_bar() {
|
||||||
if let Some(menu) = ui.begin_menu("Menu") {
|
if let Some(menu) = ui.begin_menu("Menu") {
|
||||||
@ -827,7 +827,7 @@ CTRL+click on individual component to input value.\n",
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_example_app_main_menu_bar<'a>(ui: &Ui<'a>, state: &mut State) {
|
fn show_example_app_main_menu_bar(ui: &Ui, state: &mut State) {
|
||||||
if let Some(menu_bar) = ui.begin_main_menu_bar() {
|
if let Some(menu_bar) = ui.begin_main_menu_bar() {
|
||||||
if let Some(menu) = ui.begin_menu("File") {
|
if let Some(menu) = ui.begin_menu("File") {
|
||||||
show_example_menu_file(ui, &mut state.file_menu);
|
show_example_menu_file(ui, &mut state.file_menu);
|
||||||
@ -849,7 +849,7 @@ fn show_example_app_main_menu_bar<'a>(ui: &Ui<'a>, state: &mut State) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_example_menu_file<'a>(ui: &Ui<'a>, state: &mut FileMenuState) {
|
fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) {
|
||||||
MenuItem::new("(dummy menu)").enabled(false).build(ui);
|
MenuItem::new("(dummy menu)").enabled(false).build(ui);
|
||||||
MenuItem::new("New").build(ui);
|
MenuItem::new("New").build(ui);
|
||||||
MenuItem::new("Open").shortcut("Ctrl+O").build(ui);
|
MenuItem::new("Open").shortcut("Ctrl+O").build(ui);
|
||||||
|
|||||||
@ -276,7 +276,7 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn upload_font_texture(
|
fn upload_font_texture(
|
||||||
mut fonts: imgui::FontAtlasRefMut,
|
fonts: &mut imgui::FontAtlas,
|
||||||
ctx: &Rc<Context>,
|
ctx: &Rc<Context>,
|
||||||
) -> Result<Texture, RendererError> {
|
) -> Result<Texture, RendererError> {
|
||||||
let texture = fonts.build_rgba32_texture();
|
let texture = fonts.build_rgba32_texture();
|
||||||
|
|||||||
@ -51,8 +51,8 @@ fn main() {
|
|||||||
let ui = imgui_context.frame();
|
let ui = imgui_context.frame();
|
||||||
ui.show_demo_window(&mut true);
|
ui.show_demo_window(&mut true);
|
||||||
|
|
||||||
winit_platform.prepare_render(&ui, window.window());
|
winit_platform.prepare_render(ui, window.window());
|
||||||
let draw_data = ui.render();
|
let draw_data = imgui_context.render();
|
||||||
|
|
||||||
// This is the only extra render step to add
|
// This is the only extra render step to add
|
||||||
ig_renderer
|
ig_renderer
|
||||||
|
|||||||
@ -41,8 +41,8 @@ fn main() {
|
|||||||
let ui = imgui_context.frame();
|
let ui = imgui_context.frame();
|
||||||
ui.show_demo_window(&mut true);
|
ui.show_demo_window(&mut true);
|
||||||
|
|
||||||
winit_platform.prepare_render(&ui, window.window());
|
winit_platform.prepare_render(ui, window.window());
|
||||||
let draw_data = ui.render();
|
let draw_data = imgui_context.render();
|
||||||
|
|
||||||
// Render imgui on top of it
|
// Render imgui on top of it
|
||||||
ig_renderer
|
ig_renderer
|
||||||
|
|||||||
@ -55,8 +55,8 @@ fn main() {
|
|||||||
let ui = imgui_context.frame();
|
let ui = imgui_context.frame();
|
||||||
ui.show_demo_window(&mut true);
|
ui.show_demo_window(&mut true);
|
||||||
|
|
||||||
winit_platform.prepare_render(&ui, window.window());
|
winit_platform.prepare_render(ui, window.window());
|
||||||
let draw_data = ui.render();
|
let draw_data = imgui_context.render();
|
||||||
|
|
||||||
// Render imgui on top
|
// Render imgui on top
|
||||||
ig_renderer
|
ig_renderer
|
||||||
|
|||||||
@ -56,10 +56,10 @@ fn main() {
|
|||||||
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) };
|
unsafe { gl.clear(glow::COLOR_BUFFER_BIT) };
|
||||||
|
|
||||||
let ui = imgui_context.frame();
|
let ui = imgui_context.frame();
|
||||||
textures_ui.show(&ui);
|
textures_ui.show(ui);
|
||||||
|
|
||||||
winit_platform.prepare_render(&ui, window.window());
|
winit_platform.prepare_render(ui, window.window());
|
||||||
let draw_data = ui.render();
|
let draw_data = imgui_context.render();
|
||||||
ig_renderer
|
ig_renderer
|
||||||
.render(&gl, &textures, draw_data)
|
.render(&gl, &textures, draw_data)
|
||||||
.expect("error rendering imgui");
|
.expect("error rendering imgui");
|
||||||
|
|||||||
@ -1042,7 +1042,7 @@ pub type RenderError = String;
|
|||||||
|
|
||||||
fn prepare_font_atlas<T: TextureMap>(
|
fn prepare_font_atlas<T: TextureMap>(
|
||||||
gl: &Context,
|
gl: &Context,
|
||||||
mut fonts: imgui::FontAtlasRefMut,
|
fonts: &mut imgui::FontAtlas,
|
||||||
texture_map: &mut T,
|
texture_map: &mut T,
|
||||||
) -> Result<GlTexture, InitError> {
|
) -> Result<GlTexture, InitError> {
|
||||||
#![allow(clippy::cast_possible_wrap)]
|
#![allow(clippy::cast_possible_wrap)]
|
||||||
|
|||||||
@ -93,7 +93,7 @@ pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text:
|
|||||||
|
|
||||||
/// # Clipboard
|
/// # Clipboard
|
||||||
#[allow(clippy::fn_address_comparisons)] // This is allowed because although function addresses wont be unique, we just care if its OURS
|
#[allow(clippy::fn_address_comparisons)] // This is allowed because although function addresses wont be unique, we just care if its OURS
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot
|
/// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot
|
||||||
/// be accessed
|
/// be accessed
|
||||||
pub fn clipboard_text(&self) -> Option<String> {
|
pub fn clipboard_text(&self) -> Option<String> {
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::sys;
|
|||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
|
|
||||||
/// # Columns
|
/// # Columns
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
#[doc(alias = "Columns")]
|
#[doc(alias = "Columns")]
|
||||||
pub fn columns(&self, count: i32, id: impl AsRef<str>, border: bool) {
|
pub fn columns(&self, count: i32, id: impl AsRef<str>, border: bool) {
|
||||||
unsafe { sys::igColumns(count, self.scratch_txt(id), border) }
|
unsafe { sys::igColumns(count, self.scratch_txt(id), border) }
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
use parking_lot::ReentrantMutex;
|
use parking_lot::ReentrantMutex;
|
||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::UnsafeCell;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::ops::Drop;
|
use std::ops::Drop;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::clipboard::{ClipboardBackend, ClipboardContext};
|
use crate::clipboard::{ClipboardBackend, ClipboardContext};
|
||||||
use crate::fonts::atlas::{FontAtlas, FontAtlasRefMut, FontId, SharedFontAtlas};
|
use crate::fonts::atlas::{FontAtlas, FontId, SharedFontAtlas};
|
||||||
use crate::io::Io;
|
use crate::io::Io;
|
||||||
use crate::style::Style;
|
use crate::style::Style;
|
||||||
use crate::sys;
|
|
||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
|
use crate::{sys, DrawData};
|
||||||
|
|
||||||
/// An imgui-rs context.
|
/// An imgui-rs context.
|
||||||
///
|
///
|
||||||
@ -50,7 +49,7 @@ use crate::Ui;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
raw: *mut sys::ImGuiContext,
|
raw: *mut sys::ImGuiContext,
|
||||||
shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>,
|
shared_font_atlas: Option<SharedFontAtlas>,
|
||||||
ini_filename: Option<CString>,
|
ini_filename: Option<CString>,
|
||||||
log_filename: Option<CString>,
|
log_filename: Option<CString>,
|
||||||
platform_name: Option<CString>,
|
platform_name: Option<CString>,
|
||||||
@ -60,6 +59,8 @@ pub struct Context {
|
|||||||
// we also put it in an unsafecell since we're going to give
|
// we also put it in an unsafecell since we're going to give
|
||||||
// imgui a mutable pointer to it.
|
// imgui a mutable pointer to it.
|
||||||
clipboard_ctx: Box<UnsafeCell<ClipboardContext>>,
|
clipboard_ctx: Box<UnsafeCell<ClipboardContext>>,
|
||||||
|
|
||||||
|
ui: Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This mutex needs to be used to guard all public functions that can affect the underlying
|
// This mutex needs to be used to guard all public functions that can affect the underlying
|
||||||
@ -92,7 +93,7 @@ impl Context {
|
|||||||
///
|
///
|
||||||
/// Panics if an active context already exists
|
/// Panics if an active context already exists
|
||||||
#[doc(alias = "CreateContext")]
|
#[doc(alias = "CreateContext")]
|
||||||
pub fn create_with_shared_font_atlas(shared_font_atlas: Rc<RefCell<SharedFontAtlas>>) -> Self {
|
pub fn create_with_shared_font_atlas(shared_font_atlas: SharedFontAtlas) -> Self {
|
||||||
Self::create_internal(Some(shared_font_atlas))
|
Self::create_internal(Some(shared_font_atlas))
|
||||||
}
|
}
|
||||||
/// Suspends this context so another context can be the active context.
|
/// Suspends this context so another context can be the active context.
|
||||||
@ -215,18 +216,15 @@ impl Context {
|
|||||||
io.clipboard_user_data = clipboard_ctx.get() as *mut _;
|
io.clipboard_user_data = clipboard_ctx.get() as *mut _;
|
||||||
self.clipboard_ctx = clipboard_ctx;
|
self.clipboard_ctx = clipboard_ctx;
|
||||||
}
|
}
|
||||||
fn create_internal(shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>) -> Self {
|
fn create_internal(mut shared_font_atlas: Option<SharedFontAtlas>) -> Self {
|
||||||
let _guard = CTX_MUTEX.lock();
|
let _guard = CTX_MUTEX.lock();
|
||||||
assert!(
|
assert!(
|
||||||
no_current_context(),
|
no_current_context(),
|
||||||
"A new active context cannot be created, because another one already exists"
|
"A new active context cannot be created, because another one already exists"
|
||||||
);
|
);
|
||||||
|
|
||||||
let shared_font_atlas_ptr = match &shared_font_atlas {
|
let shared_font_atlas_ptr = match &mut shared_font_atlas {
|
||||||
Some(shared_font_atlas) => {
|
Some(shared_font_atlas) => shared_font_atlas.as_ptr_mut(),
|
||||||
let borrowed_font_atlas = shared_font_atlas.borrow();
|
|
||||||
borrowed_font_atlas.0
|
|
||||||
}
|
|
||||||
None => ptr::null_mut(),
|
None => ptr::null_mut(),
|
||||||
};
|
};
|
||||||
// Dear ImGui implicitly sets the current context during igCreateContext if the current
|
// Dear ImGui implicitly sets the current context during igCreateContext if the current
|
||||||
@ -241,6 +239,9 @@ impl Context {
|
|||||||
platform_name: None,
|
platform_name: None,
|
||||||
renderer_name: None,
|
renderer_name: None,
|
||||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||||
|
ui: Ui {
|
||||||
|
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_current_context(&self) -> bool {
|
fn is_current_context(&self) -> bool {
|
||||||
@ -256,6 +257,10 @@ impl Drop for Context {
|
|||||||
// If this context is the active context, Dear ImGui automatically deactivates it during
|
// If this context is the active context, Dear ImGui automatically deactivates it during
|
||||||
// destruction
|
// destruction
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// end the frame if necessary...
|
||||||
|
if !sys::igGetCurrentContext().is_null() && sys::igGetFrameCount() > 0 {
|
||||||
|
sys::igEndFrame();
|
||||||
|
}
|
||||||
sys::igDestroyContext(self.raw);
|
sys::igDestroyContext(self.raw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,8 +294,9 @@ impl SuspendedContext {
|
|||||||
pub fn create() -> Self {
|
pub fn create() -> Self {
|
||||||
Self::create_internal(None)
|
Self::create_internal(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new suspended imgui-rs context with a shared font atlas.
|
/// Creates a new suspended imgui-rs context with a shared font atlas.
|
||||||
pub fn create_with_shared_font_atlas(shared_font_atlas: Rc<RefCell<SharedFontAtlas>>) -> Self {
|
pub fn create_with_shared_font_atlas(shared_font_atlas: SharedFontAtlas) -> Self {
|
||||||
Self::create_internal(Some(shared_font_atlas))
|
Self::create_internal(Some(shared_font_atlas))
|
||||||
}
|
}
|
||||||
/// Attempts to activate this suspended context.
|
/// Attempts to activate this suspended context.
|
||||||
@ -311,7 +317,7 @@ impl SuspendedContext {
|
|||||||
Err(self)
|
Err(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn create_internal(shared_font_atlas: Option<Rc<RefCell<SharedFontAtlas>>>) -> Self {
|
fn create_internal(shared_font_atlas: Option<SharedFontAtlas>) -> Self {
|
||||||
let _guard = CTX_MUTEX.lock();
|
let _guard = CTX_MUTEX.lock();
|
||||||
let raw = unsafe { sys::igCreateContext(ptr::null_mut()) };
|
let raw = unsafe { sys::igCreateContext(ptr::null_mut()) };
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
@ -322,6 +328,9 @@ impl SuspendedContext {
|
|||||||
platform_name: None,
|
platform_name: None,
|
||||||
renderer_name: None,
|
renderer_name: None,
|
||||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||||
|
ui: Ui {
|
||||||
|
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if ctx.is_current_context() {
|
if ctx.is_current_context() {
|
||||||
// Oops, the context was activated -> deactivate
|
// Oops, the context was activated -> deactivate
|
||||||
@ -403,7 +412,7 @@ fn test_suspend_failure() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_shared_font_atlas() {
|
fn test_shared_font_atlas() {
|
||||||
let _guard = crate::test::TEST_MUTEX.lock();
|
let _guard = crate::test::TEST_MUTEX.lock();
|
||||||
let atlas = Rc::new(RefCell::new(SharedFontAtlas::create()));
|
let atlas = SharedFontAtlas::create();
|
||||||
let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone());
|
let suspended1 = SuspendedContext::create_with_shared_font_atlas(atlas.clone());
|
||||||
let mut ctx2 = Context::create_with_shared_font_atlas(atlas);
|
let mut ctx2 = Context::create_with_shared_font_atlas(atlas);
|
||||||
{
|
{
|
||||||
@ -414,17 +423,6 @@ fn test_shared_font_atlas() {
|
|||||||
let _borrow = ctx.fonts();
|
let _borrow = ctx.fonts();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_shared_font_atlas_borrow_panic() {
|
|
||||||
let _guard = crate::test::TEST_MUTEX.lock();
|
|
||||||
let atlas = Rc::new(RefCell::new(SharedFontAtlas::create()));
|
|
||||||
let _suspended = SuspendedContext::create_with_shared_font_atlas(atlas.clone());
|
|
||||||
let mut ctx = Context::create_with_shared_font_atlas(atlas.clone());
|
|
||||||
let _borrow1 = atlas.borrow();
|
|
||||||
let _borrow2 = ctx.fonts();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ini_load_save() {
|
fn test_ini_load_save() {
|
||||||
let (_guard, mut ctx) = crate::test::test_ctx();
|
let (_guard, mut ctx) = crate::test::test_ctx();
|
||||||
@ -498,45 +496,51 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Returns a mutable reference to the font atlas.
|
/// Returns a mutable reference to the font atlas.
|
||||||
///
|
pub fn fonts(&mut self) -> &mut FontAtlas {
|
||||||
/// # Panics
|
// we take this with an `&mut Self` here, which means
|
||||||
///
|
// that we can't get the sharedfontatlas through safe code
|
||||||
/// Panics if the context uses a shared font atlas that is already borrowed
|
// otherwise
|
||||||
pub fn fonts(&mut self) -> FontAtlasRefMut<'_> {
|
unsafe { &mut *(self.io_mut().fonts as *mut FontAtlas) }
|
||||||
match self.shared_font_atlas {
|
|
||||||
Some(ref font_atlas) => FontAtlasRefMut::Shared(font_atlas.borrow_mut()),
|
|
||||||
None => unsafe {
|
|
||||||
// safe because FontAtlas is a transparent wrapper around sys::ImFontAtlas
|
|
||||||
let fonts = &mut *(self.io_mut().fonts as *mut FontAtlas);
|
|
||||||
FontAtlasRefMut::Owned(fonts)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Attempts to clone the interior shared font atlas **if it exists**.
|
||||||
|
pub fn clone_shared_font_atlas(&mut self) -> Option<SharedFontAtlas> {
|
||||||
|
self.shared_font_atlas.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Starts a new frame. Use [`new_frame`] instead.
|
||||||
|
///
|
||||||
|
/// [`new_frame`]: Self::new_frame
|
||||||
|
pub fn frame(&mut self) -> &mut Ui {
|
||||||
|
self.new_frame()
|
||||||
|
}
|
||||||
|
|
||||||
/// Starts a new frame and returns an `Ui` instance for constructing a user interface.
|
/// Starts a new frame and returns an `Ui` instance for constructing a user interface.
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if the context uses a shared font atlas that is already borrowed
|
|
||||||
#[doc(alias = "NewFame")]
|
#[doc(alias = "NewFame")]
|
||||||
pub fn frame(&mut self) -> Ui<'_> {
|
pub fn new_frame(&mut self) -> &mut Ui {
|
||||||
// Clear default font if it no longer exists. This could be an error in the future
|
// Clear default font if it no longer exists. This could be an error in the future
|
||||||
let default_font = self.io().font_default;
|
let default_font = self.io().font_default;
|
||||||
if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() {
|
if !default_font.is_null() && self.fonts().get_font(FontId(default_font)).is_none() {
|
||||||
self.io_mut().font_default = ptr::null_mut();
|
self.io_mut().font_default = ptr::null_mut();
|
||||||
}
|
}
|
||||||
// NewFrame/Render/EndFrame mutate the font atlas so we need exclusive access to it
|
|
||||||
let font_atlas = self
|
|
||||||
.shared_font_atlas
|
|
||||||
.as_ref()
|
|
||||||
.map(|font_atlas| font_atlas.borrow_mut());
|
|
||||||
// TODO: precondition checks
|
// TODO: precondition checks
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igNewFrame();
|
sys::igNewFrame();
|
||||||
}
|
}
|
||||||
Ui {
|
|
||||||
ctx: self,
|
&mut self.ui
|
||||||
font_atlas,
|
}
|
||||||
buffer: crate::UiBuffer::new(1024).into(),
|
|
||||||
|
/// Renders the frame and returns a reference to the resulting draw data.
|
||||||
|
///
|
||||||
|
/// This should only be called after calling [`new_frame`].
|
||||||
|
///
|
||||||
|
/// [`new_frame`]: Self::new_frame
|
||||||
|
#[doc(alias = "Render", alias = "GetDrawData")]
|
||||||
|
pub fn render(&mut self) -> &DrawData {
|
||||||
|
unsafe {
|
||||||
|
sys::igRender();
|
||||||
|
&*(sys::igGetDrawData() as *mut DrawData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,7 +74,7 @@ bitflags!(
|
|||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use imgui::*;
|
/// # use imgui::*;
|
||||||
/// fn show_ui(ui: &Ui<'_>) {
|
/// fn show_ui(ui: &Ui) {
|
||||||
/// ui.button("Hello, I am a drag source!");
|
/// ui.button("Hello, I am a drag source!");
|
||||||
///
|
///
|
||||||
/// // Creates an empty DragSource with no tooltip
|
/// // Creates an empty DragSource with no tooltip
|
||||||
@ -141,7 +141,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use imgui::*;
|
/// # use imgui::*;
|
||||||
/// fn show_ui(ui: &Ui<'_>, drop_message: &mut Option<String>) {
|
/// fn show_ui(ui: &Ui, drop_message: &mut Option<String>) {
|
||||||
/// ui.button("Drag me!");
|
/// ui.button("Drag me!");
|
||||||
///
|
///
|
||||||
/// let drag_drop_name = "Test Drag";
|
/// let drag_drop_name = "Test Drag";
|
||||||
@ -175,7 +175,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
/// If you want to pass a simple integer or other "plain old data", take a look at
|
/// If you want to pass a simple integer or other "plain old data", take a look at
|
||||||
/// [begin_payload](Self::begin_payload).
|
/// [begin_payload](Self::begin_payload).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<DragDropSourceToolTip<'ui>> {
|
pub fn begin<'ui>(self, ui: &Ui) -> Option<DragDropSourceToolTip<'ui>> {
|
||||||
self.begin_payload(ui, ())
|
self.begin_payload(ui, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use imgui::*;
|
/// # use imgui::*;
|
||||||
/// fn show_ui(ui: &Ui<'_>) {
|
/// fn show_ui(ui: &Ui) {
|
||||||
/// ui.button("Drag me!");
|
/// ui.button("Drag me!");
|
||||||
///
|
///
|
||||||
/// let drag_drop_name = "Test Drag";
|
/// let drag_drop_name = "Test Drag";
|
||||||
@ -224,7 +224,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn begin_payload<'ui, P: Copy + 'static>(
|
pub fn begin_payload<'ui, P: Copy + 'static>(
|
||||||
self,
|
self,
|
||||||
ui: &Ui<'ui>,
|
ui: &Ui,
|
||||||
payload: P,
|
payload: P,
|
||||||
) -> Option<DragDropSourceToolTip<'ui>> {
|
) -> Option<DragDropSourceToolTip<'ui>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -266,7 +266,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn begin_payload_unchecked<'ui>(
|
pub unsafe fn begin_payload_unchecked<'ui>(
|
||||||
&self,
|
&self,
|
||||||
ui: &Ui<'ui>,
|
ui: &Ui,
|
||||||
ptr: *const ffi::c_void,
|
ptr: *const ffi::c_void,
|
||||||
size: usize,
|
size: usize,
|
||||||
) -> Option<DragDropSourceToolTip<'ui>> {
|
) -> Option<DragDropSourceToolTip<'ui>> {
|
||||||
@ -283,7 +283,7 @@ impl<T: AsRef<str>> DragDropSource<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A helper struct for RAII drap-drop support.
|
/// A helper struct for RAII drap-drop support.
|
||||||
pub struct DragDropSourceToolTip<'ui>(PhantomData<Ui<'ui>>);
|
pub struct DragDropSourceToolTip<'ui>(PhantomData<&'ui Ui>);
|
||||||
|
|
||||||
impl DragDropSourceToolTip<'_> {
|
impl DragDropSourceToolTip<'_> {
|
||||||
/// Creates a new tooltip internally.
|
/// Creates a new tooltip internally.
|
||||||
@ -310,7 +310,7 @@ impl Drop for DragDropSourceToolTip<'_> {
|
|||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// # use imgui::*;
|
/// # use imgui::*;
|
||||||
/// fn show_ui(ui: &Ui<'_>) {
|
/// fn show_ui(ui: &Ui) {
|
||||||
/// // Drop something on this button please!
|
/// // Drop something on this button please!
|
||||||
/// ui.button("Hello, I am a drag Target!");
|
/// ui.button("Hello, I am a drag Target!");
|
||||||
///
|
///
|
||||||
@ -339,14 +339,14 @@ impl Drop for DragDropSourceToolTip<'_> {
|
|||||||
/// on this struct. Each of these methods will spit out a _Payload struct with an increasing
|
/// on this struct. Each of these methods will spit out a _Payload struct with an increasing
|
||||||
/// amount of information on the Payload. The absolute safest solution is [accept_payload_empty](Self::accept_payload_empty).
|
/// amount of information on the Payload. The absolute safest solution is [accept_payload_empty](Self::accept_payload_empty).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DragDropTarget<'ui>(&'ui Ui<'ui>);
|
pub struct DragDropTarget<'ui>(&'ui Ui);
|
||||||
|
|
||||||
impl<'ui> DragDropTarget<'ui> {
|
impl<'ui> DragDropTarget<'ui> {
|
||||||
/// Creates a new DragDropTarget, holding the [Ui]'s lifetime for the duration
|
/// Creates a new DragDropTarget, holding the [Ui]'s lifetime for the duration
|
||||||
/// of its existence. This is required since this struct runs some code on its Drop
|
/// of its existence. This is required since this struct runs some code on its Drop
|
||||||
/// to end the DragDropTarget code.
|
/// to end the DragDropTarget code.
|
||||||
#[doc(alias = "BeginDragDropTarget")]
|
#[doc(alias = "BeginDragDropTarget")]
|
||||||
pub fn new(ui: &'ui Ui<'ui>) -> Option<Self> {
|
pub fn new(ui: &'ui Ui) -> Option<Self> {
|
||||||
let should_begin = unsafe { sys::igBeginDragDropTarget() };
|
let should_begin = unsafe { sys::igBeginDragDropTarget() };
|
||||||
if should_begin {
|
if should_begin {
|
||||||
Some(Self(ui))
|
Some(Self(ui))
|
||||||
|
|||||||
@ -75,7 +75,7 @@ enum DrawListType {
|
|||||||
pub struct DrawListMut<'ui> {
|
pub struct DrawListMut<'ui> {
|
||||||
draw_list_type: DrawListType,
|
draw_list_type: DrawListType,
|
||||||
draw_list: *mut ImDrawList,
|
draw_list: *mut ImDrawList,
|
||||||
_phantom: PhantomData<&'ui Ui<'ui>>,
|
_phantom: PhantomData<&'ui Ui>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock for each variant of draw list. See https://github.com/imgui-rs/imgui-rs/issues/488
|
// Lock for each variant of draw list. See https://github.com/imgui-rs/imgui-rs/issues/488
|
||||||
@ -124,7 +124,7 @@ impl<'ui> DrawListMut<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "GetWindowDrawList")]
|
#[doc(alias = "GetWindowDrawList")]
|
||||||
pub(crate) fn window(_: &Ui<'ui>) -> Self {
|
pub(crate) fn window(_: &Ui) -> Self {
|
||||||
Self::lock_draw_list(DrawListType::Window);
|
Self::lock_draw_list(DrawListType::Window);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -135,7 +135,7 @@ impl<'ui> DrawListMut<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "GetBackgroundDrawList")]
|
#[doc(alias = "GetBackgroundDrawList")]
|
||||||
pub(crate) fn background(_: &Ui<'ui>) -> Self {
|
pub(crate) fn background(_: &Ui) -> Self {
|
||||||
Self::lock_draw_list(DrawListType::Background);
|
Self::lock_draw_list(DrawListType::Background);
|
||||||
Self {
|
Self {
|
||||||
draw_list: unsafe { sys::igGetBackgroundDrawList() },
|
draw_list: unsafe { sys::igGetBackgroundDrawList() },
|
||||||
@ -145,7 +145,7 @@ impl<'ui> DrawListMut<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[doc(alias = "GetForegroundDrawList")]
|
#[doc(alias = "GetForegroundDrawList")]
|
||||||
pub(crate) fn foreground(_: &Ui<'ui>) -> Self {
|
pub(crate) fn foreground(_: &Ui) -> Self {
|
||||||
Self::lock_draw_list(DrawListType::Foreground);
|
Self::lock_draw_list(DrawListType::Foreground);
|
||||||
Self {
|
Self {
|
||||||
draw_list: unsafe { sys::igGetForegroundDrawList() },
|
draw_list: unsafe { sys::igGetForegroundDrawList() },
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use std::cell;
|
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::os::raw::{c_int, c_uchar, c_void};
|
use std::os::raw::{c_int, c_uchar, c_void};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use crate::fonts::font::Font;
|
use crate::fonts::font::Font;
|
||||||
@ -433,76 +432,95 @@ pub struct FontAtlasTexture<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A font atlas that can be shared between contexts
|
/// A font atlas that can be shared between contexts
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SharedFontAtlas(pub(crate) *mut sys::ImFontAtlas);
|
pub struct SharedFontAtlas(pub(crate) Rc<*mut sys::ImFontAtlas>);
|
||||||
|
|
||||||
|
impl std::ops::Deref for SharedFontAtlas {
|
||||||
|
type Target = Rc<*mut sys::ImFontAtlas>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for SharedFontAtlas {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SharedFontAtlas {
|
impl SharedFontAtlas {
|
||||||
#[doc(alias = "ImFontAtlas", alias = "ImFontAtlas::ImFontAtlas")]
|
#[doc(alias = "ImFontAtlas", alias = "ImFontAtlas::ImFontAtlas")]
|
||||||
pub fn create() -> SharedFontAtlas {
|
pub fn create() -> SharedFontAtlas {
|
||||||
SharedFontAtlas(unsafe { sys::ImFontAtlas_ImFontAtlas() })
|
SharedFontAtlas(unsafe { Rc::new(sys::ImFontAtlas_ImFontAtlas()) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a raw pointer to the underlying `ImFontAtlas`.
|
||||||
|
pub fn as_ptr(&self) -> *const sys::ImFontAtlas {
|
||||||
|
*self.0 as *const _
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a raw pointer to the underlying `ImFontAtlas`.
|
||||||
|
pub fn as_ptr_mut(&mut self) -> *mut sys::ImFontAtlas {
|
||||||
|
*self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SharedFontAtlas {
|
impl Drop for SharedFontAtlas {
|
||||||
#[doc(alias = "ImFontAtlas::Destory")]
|
#[doc(alias = "ImFontAtlas::Destory")]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { sys::ImFontAtlas_destroy(self.0) };
|
// if we're about to drop the last one...
|
||||||
}
|
if Rc::strong_count(&self.0) == 1 {
|
||||||
}
|
unsafe { sys::ImFontAtlas_destroy(*self.0) };
|
||||||
|
|
||||||
impl Deref for SharedFontAtlas {
|
|
||||||
type Target = FontAtlas;
|
|
||||||
fn deref(&self) -> &FontAtlas {
|
|
||||||
unsafe { &*(self.0 as *const FontAtlas) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for SharedFontAtlas {
|
|
||||||
fn deref_mut(&mut self) -> &mut FontAtlas {
|
|
||||||
unsafe { &mut *(self.0 as *mut FontAtlas) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An immutably borrowed reference to a (possibly shared) font atlas
|
|
||||||
pub enum FontAtlasRef<'a> {
|
|
||||||
Owned(&'a FontAtlas),
|
|
||||||
Shared(&'a cell::RefMut<'a, SharedFontAtlas>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Deref for FontAtlasRef<'a> {
|
|
||||||
type Target = FontAtlas;
|
|
||||||
fn deref(&self) -> &FontAtlas {
|
|
||||||
use self::FontAtlasRef::*;
|
|
||||||
match self {
|
|
||||||
Owned(atlas) => atlas,
|
|
||||||
Shared(cell) => cell,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mutably borrowed reference to a (possibly shared) font atlas
|
// /// An immutably borrowed reference to a (possibly shared) font atlas
|
||||||
pub enum FontAtlasRefMut<'a> {
|
// pub enum FontAtlasRef<'a> {
|
||||||
Owned(&'a mut FontAtlas),
|
// Owned(&'a FontAtlas),
|
||||||
Shared(cell::RefMut<'a, SharedFontAtlas>),
|
// Shared(&'a cell::RefMut<'a, SharedFontAtlas>),
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<'a> Deref for FontAtlasRefMut<'a> {
|
// impl<'a> Deref for FontAtlasRef<'a> {
|
||||||
type Target = FontAtlas;
|
// type Target = FontAtlas;
|
||||||
fn deref(&self) -> &FontAtlas {
|
// fn deref(&self) -> &FontAtlas {
|
||||||
use self::FontAtlasRefMut::*;
|
// use self::FontAtlasRef::*;
|
||||||
match self {
|
// match self {
|
||||||
Owned(atlas) => atlas,
|
// Owned(atlas) => atlas,
|
||||||
Shared(cell) => cell,
|
// Shared(cell) => {
|
||||||
}
|
// let font_atlas: &SharedFontAtlas = &cell;
|
||||||
}
|
// let font_atlas: &FontAtlas = &font_atlas;
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DerefMut for FontAtlasRefMut<'a> {
|
// todo!()
|
||||||
fn deref_mut(&mut self) -> &mut FontAtlas {
|
// }
|
||||||
use self::FontAtlasRefMut::*;
|
// }
|
||||||
match self {
|
// }
|
||||||
Owned(atlas) => atlas,
|
// }
|
||||||
Shared(cell) => cell,
|
|
||||||
}
|
// /// A mutably borrowed reference to a (possibly shared) font atlas
|
||||||
}
|
// pub enum FontAtlasRefMut<'a> {
|
||||||
}
|
// Owned(&'a mut FontAtlas),
|
||||||
|
// Shared(cell::RefMut<'a, SharedFontAtlas>),
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a> Deref for FontAtlasRefMut<'a> {
|
||||||
|
// type Target = FontAtlas;
|
||||||
|
// fn deref(&self) -> &FontAtlas {
|
||||||
|
// use self::FontAtlasRefMut::*;
|
||||||
|
// match self {
|
||||||
|
// Owned(atlas) => atlas,
|
||||||
|
// Shared(cell) => cell,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<'a> DerefMut for FontAtlasRefMut<'a> {
|
||||||
|
// fn deref_mut(&mut self) -> &mut FontAtlas {
|
||||||
|
// use self::FontAtlasRefMut::*;
|
||||||
|
// match self {
|
||||||
|
// Owned(atlas) => atlas,
|
||||||
|
// Shared(cell) => cell,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
@ -8,7 +8,7 @@ pub mod glyph;
|
|||||||
pub mod glyph_ranges;
|
pub mod glyph_ranges;
|
||||||
|
|
||||||
/// # Fonts
|
/// # Fonts
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns the current font
|
/// Returns the current font
|
||||||
#[doc(alias = "GetFont")]
|
#[doc(alias = "GetFont")]
|
||||||
pub fn current_font(&self) -> &Font {
|
pub fn current_font(&self) -> &Font {
|
||||||
|
|||||||
@ -91,7 +91,7 @@ impl FocusedWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Input: Keyboard
|
/// # Input: Keyboard
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns the key index of the given key identifier.
|
/// Returns the key index of the given key identifier.
|
||||||
///
|
///
|
||||||
/// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]`
|
/// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]`
|
||||||
|
|||||||
@ -89,7 +89,7 @@ fn test_mouse_cursor_variants() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Input: Mouse
|
/// # Input: Mouse
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns true if the given mouse button is held down.
|
/// Returns true if the given mouse button is held down.
|
||||||
///
|
///
|
||||||
/// Equivalent to indexing the Io struct with the button, e.g. `ui.io()[button]`.
|
/// Equivalent to indexing the Io struct with the button, e.g. `ui.io()[button]`.
|
||||||
@ -237,41 +237,46 @@ fn test_mouse_down_clicked_released() {
|
|||||||
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_down = [false; 5];
|
ctx.io_mut().mouse_down = [false; 5];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_down(button));
|
assert!(!ui.is_mouse_down(button));
|
||||||
assert!(!ui.is_any_mouse_down());
|
assert!(!ui.is_any_mouse_down());
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_released(button));
|
assert!(!ui.is_mouse_released(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_down(button));
|
assert!(ui.is_mouse_down(button));
|
||||||
assert!(ui.is_any_mouse_down());
|
assert!(ui.is_any_mouse_down());
|
||||||
assert!(ui.is_mouse_clicked(button));
|
assert!(ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_released(button));
|
assert!(!ui.is_mouse_released(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_down(button));
|
assert!(ui.is_mouse_down(button));
|
||||||
assert!(ui.is_any_mouse_down());
|
assert!(ui.is_any_mouse_down());
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_released(button));
|
assert!(!ui.is_mouse_released(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = false;
|
ctx.io_mut()[button] = false;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_down(button));
|
assert!(!ui.is_mouse_down(button));
|
||||||
assert!(!ui.is_any_mouse_down());
|
assert!(!ui.is_any_mouse_down());
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(ui.is_mouse_released(button));
|
assert!(ui.is_mouse_released(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_down(button));
|
assert!(!ui.is_mouse_down(button));
|
||||||
assert!(!ui.is_any_mouse_down());
|
assert!(!ui.is_any_mouse_down());
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_released(button));
|
assert!(!ui.is_mouse_released(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,6 +284,7 @@ fn test_mouse_down_clicked_released() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_mouse_double_click() {
|
fn test_mouse_double_click() {
|
||||||
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
||||||
|
|
||||||
// Workaround for dear imgui bug/feature:
|
// Workaround for dear imgui bug/feature:
|
||||||
// If a button is clicked before io.mouse_double_click_time seconds has passed after the
|
// If a button is clicked before io.mouse_double_click_time seconds has passed after the
|
||||||
// context is initialized, the single click is interpreted as a double-click. This happens
|
// context is initialized, the single click is interpreted as a double-click. This happens
|
||||||
@ -287,44 +293,51 @@ fn test_mouse_double_click() {
|
|||||||
{
|
{
|
||||||
// Pass one second of time
|
// Pass one second of time
|
||||||
ctx.io_mut().delta_time = 1.0;
|
ctx.io_mut().delta_time = 1.0;
|
||||||
let _ = ctx.frame();
|
let _ = ctx.new_frame();
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
// Fast clicks
|
// Fast clicks
|
||||||
ctx.io_mut().delta_time = 1.0 / 60.0;
|
ctx.io_mut().delta_time = 1.0 / 60.0;
|
||||||
for &button in MouseButton::VARIANTS.iter() {
|
for &button in MouseButton::VARIANTS.iter() {
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_down = [false; 5];
|
ctx.io_mut().mouse_down = [false; 5];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_clicked(button));
|
assert!(ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = false;
|
ctx.io_mut()[button] = false;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_clicked(button));
|
assert!(ui.is_mouse_clicked(button));
|
||||||
assert!(ui.is_mouse_double_clicked(button));
|
assert!(ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Slow clicks
|
// Slow clicks
|
||||||
@ -332,37 +345,43 @@ fn test_mouse_double_click() {
|
|||||||
for &button in MouseButton::VARIANTS.iter() {
|
for &button in MouseButton::VARIANTS.iter() {
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_down = [false; 5];
|
ctx.io_mut().mouse_down = [false; 5];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_clicked(button));
|
assert!(ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = false;
|
ctx.io_mut()[button] = false;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_clicked(button));
|
assert!(ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_clicked(button));
|
assert!(!ui.is_mouse_clicked(button));
|
||||||
assert!(!ui.is_mouse_double_clicked(button));
|
assert!(!ui.is_mouse_double_clicked(button));
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,7 +389,7 @@ fn test_mouse_double_click() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_set_get_mouse_cursor() {
|
fn test_set_get_mouse_cursor() {
|
||||||
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
let (_guard, mut ctx) = crate::test::test_ctx_initialized();
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
ui.set_mouse_cursor(None);
|
ui.set_mouse_cursor(None);
|
||||||
assert_eq!(None, ui.mouse_cursor());
|
assert_eq!(None, ui.mouse_cursor());
|
||||||
ui.set_mouse_cursor(Some(MouseCursor::Hand));
|
ui.set_mouse_cursor(Some(MouseCursor::Hand));
|
||||||
@ -384,7 +403,7 @@ fn test_mouse_drags() {
|
|||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [0.0, 0.0];
|
ctx.io_mut().mouse_pos = [0.0, 0.0];
|
||||||
ctx.io_mut().mouse_down = [false; 5];
|
ctx.io_mut().mouse_down = [false; 5];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_dragging(button));
|
assert!(!ui.is_mouse_dragging(button));
|
||||||
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
||||||
@ -392,10 +411,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 0.0]
|
[0.0, 0.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_dragging(button));
|
assert!(!ui.is_mouse_dragging(button));
|
||||||
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
||||||
@ -403,10 +423,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 0.0]
|
[0.0, 0.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [0.0, 100.0];
|
ctx.io_mut().mouse_pos = [0.0, 100.0];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_dragging(button));
|
assert!(ui.is_mouse_dragging(button));
|
||||||
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 100.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 100.0]);
|
||||||
@ -414,10 +435,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 0.0]
|
[0.0, 0.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [0.0, 200.0];
|
ctx.io_mut().mouse_pos = [0.0, 200.0];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_dragging(button));
|
assert!(ui.is_mouse_dragging(button));
|
||||||
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 200.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 200.0]);
|
||||||
@ -425,11 +447,12 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 200.0]
|
[0.0, 200.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [10.0, 10.0];
|
ctx.io_mut().mouse_pos = [10.0, 10.0];
|
||||||
ctx.io_mut()[button] = false;
|
ctx.io_mut()[button] = false;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_dragging(button));
|
assert!(!ui.is_mouse_dragging(button));
|
||||||
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [10.0, 10.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [10.0, 10.0]);
|
||||||
@ -437,10 +460,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[10.0, 10.0]
|
[10.0, 10.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut()[button] = true;
|
ctx.io_mut()[button] = true;
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(!ui.is_mouse_dragging(button));
|
assert!(!ui.is_mouse_dragging(button));
|
||||||
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(!ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [0.0, 0.0]);
|
||||||
@ -448,10 +472,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 0.0]
|
[0.0, 0.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [180.0, 180.0];
|
ctx.io_mut().mouse_pos = [180.0, 180.0];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_dragging(button));
|
assert!(ui.is_mouse_dragging(button));
|
||||||
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [170.0, 170.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [170.0, 170.0]);
|
||||||
@ -467,10 +492,11 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[0.0, 0.0]
|
[0.0, 0.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ctx.io_mut().mouse_pos = [200.0, 200.0];
|
ctx.io_mut().mouse_pos = [200.0, 200.0];
|
||||||
let ui = ctx.frame();
|
let ui = ctx.new_frame();
|
||||||
assert!(ui.is_mouse_dragging(button));
|
assert!(ui.is_mouse_dragging(button));
|
||||||
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
assert!(ui.is_mouse_dragging_with_threshold(button, 200.0));
|
||||||
assert_eq!(ui.mouse_drag_delta_with_button(button), [20.0, 20.0]);
|
assert_eq!(ui.mouse_drag_delta_with_button(button), [20.0, 20.0]);
|
||||||
@ -478,6 +504,7 @@ fn test_mouse_drags() {
|
|||||||
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
ui.mouse_drag_delta_with_threshold(button, 200.0),
|
||||||
[20.0, 20.0]
|
[20.0, 20.0]
|
||||||
);
|
);
|
||||||
|
let _ = ctx.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -166,7 +166,7 @@ pub struct InputText<'ui, 'p, L, H = &'static str, T = PassthroughCallback> {
|
|||||||
buf: &'p mut String,
|
buf: &'p mut String,
|
||||||
callback_handler: T,
|
callback_handler: T,
|
||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L: AsRef<str>> InputText<'ui, 'p, L> {
|
impl<'ui, 'p, L: AsRef<str>> InputText<'ui, 'p, L> {
|
||||||
@ -184,7 +184,7 @@ impl<'ui, 'p, L: AsRef<str>> InputText<'ui, 'p, L> {
|
|||||||
/// your string.
|
/// your string.
|
||||||
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
|
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
|
||||||
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
|
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String) -> Self {
|
||||||
InputText {
|
InputText {
|
||||||
label,
|
label,
|
||||||
hint: None,
|
hint: None,
|
||||||
@ -343,7 +343,7 @@ pub struct InputTextMultiline<'ui, 'p, L, T = PassthroughCallback> {
|
|||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
size: [f32; 2],
|
size: [f32; 2],
|
||||||
callback_handler: T,
|
callback_handler: T,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback> {
|
impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback> {
|
||||||
@ -361,7 +361,7 @@ impl<'ui, 'p, L: AsRef<str>> InputTextMultiline<'ui, 'p, L, PassthroughCallback>
|
|||||||
/// your string.
|
/// your string.
|
||||||
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
|
/// 3. Truncations by ImGui appear to be done primarily by insertions of `\0` to the truncation point.
|
||||||
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
|
/// We will handle this for you and edit the string "properly" too, but this might show up in callbacks.
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, buf: &'p mut String, size: impl Into<MintVec2>) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, buf: &'p mut String, size: impl Into<MintVec2>) -> Self {
|
||||||
InputTextMultiline {
|
InputTextMultiline {
|
||||||
label,
|
label,
|
||||||
buf,
|
buf,
|
||||||
@ -482,11 +482,11 @@ pub struct InputInt<'ui, 'p, L> {
|
|||||||
step: i32,
|
step: i32,
|
||||||
step_fast: i32,
|
step_fast: i32,
|
||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L: AsRef<str>> InputInt<'ui, 'p, L> {
|
impl<'ui, 'p, L: AsRef<str>> InputInt<'ui, 'p, L> {
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut i32) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, value: &'p mut i32) -> Self {
|
||||||
InputInt {
|
InputInt {
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
@ -520,11 +520,11 @@ pub struct InputFloat<'ui, 'p, L> {
|
|||||||
step: f32,
|
step: f32,
|
||||||
step_fast: f32,
|
step_fast: f32,
|
||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L: AsRef<str>> InputFloat<'ui, 'p, L> {
|
impl<'ui, 'p, L: AsRef<str>> InputFloat<'ui, 'p, L> {
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut f32) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, value: &'p mut f32) -> Self {
|
||||||
InputFloat {
|
InputFloat {
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
@ -559,7 +559,7 @@ macro_rules! impl_input_floatn {
|
|||||||
label: L,
|
label: L,
|
||||||
value: &'p mut T,
|
value: &'p mut T,
|
||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L, T> $InputFloatN<'ui, 'p, L, T>
|
impl<'ui, 'p, L, T> $InputFloatN<'ui, 'p, L, T>
|
||||||
@ -568,7 +568,7 @@ macro_rules! impl_input_floatn {
|
|||||||
T: Copy + Into<$MINT_TARGET>,
|
T: Copy + Into<$MINT_TARGET>,
|
||||||
$MINT_TARGET: Into<T> + Into<[f32; $N]>,
|
$MINT_TARGET: Into<T> + Into<[f32; $N]>,
|
||||||
{
|
{
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self {
|
||||||
$InputFloatN {
|
$InputFloatN {
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
@ -614,7 +614,7 @@ macro_rules! impl_input_intn {
|
|||||||
label: L,
|
label: L,
|
||||||
value: &'p mut T,
|
value: &'p mut T,
|
||||||
flags: InputTextFlags,
|
flags: InputTextFlags,
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, L, T> $InputIntN<'ui, 'p, L, T>
|
impl<'ui, 'p, L, T> $InputIntN<'ui, 'p, L, T>
|
||||||
@ -623,7 +623,7 @@ macro_rules! impl_input_intn {
|
|||||||
T: Copy + Into<$MINT_TARGET>,
|
T: Copy + Into<$MINT_TARGET>,
|
||||||
$MINT_TARGET: Into<T> + Into<[i32; $N]>,
|
$MINT_TARGET: Into<T> + Into<[i32; $N]>,
|
||||||
{
|
{
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: L, value: &'p mut T) -> Self {
|
pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self {
|
||||||
$InputIntN {
|
$InputIntN {
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ create_token!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// # Cursor / Layout
|
/// # Cursor / Layout
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Renders a separator (generally horizontal).
|
/// Renders a separator (generally horizontal).
|
||||||
///
|
///
|
||||||
/// This becomes a vertical separator inside a menu bar or in horizontal layout mode.
|
/// This becomes a vertical separator inside a menu bar or in horizontal layout mode.
|
||||||
|
|||||||
115
imgui/src/lib.rs
115
imgui/src/lib.rs
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
pub extern crate imgui_sys as sys;
|
pub extern crate imgui_sys as sys;
|
||||||
|
|
||||||
|
use std::cell;
|
||||||
use std::os::raw::{c_char, c_void};
|
use std::os::raw::{c_char, c_void};
|
||||||
|
|
||||||
pub use self::clipboard::*;
|
pub use self::clipboard::*;
|
||||||
@ -115,16 +116,31 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A temporary reference for building the user interface for one frame
|
/// A reference for building the user interface for one frame
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Ui<'ui> {
|
pub struct Ui {
|
||||||
ctx: &'ui Context,
|
/// our scratch sheet
|
||||||
font_atlas: Option<std::cell::RefMut<'ui, SharedFontAtlas>>,
|
buffer: cell::UnsafeCell<string::UiBuffer>,
|
||||||
// imgui isn't mutli-threaded -- so no one will ever access twice.
|
|
||||||
buffer: std::cell::UnsafeCell<string::UiBuffer>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
|
/// This provides access to the backing scratch buffer that we use to write
|
||||||
|
/// strings, along with null-terminators, before we pass normal Rust strs to
|
||||||
|
/// Dear ImGui.
|
||||||
|
///
|
||||||
|
/// This is given as a get-out-of-jail free card if you need to handle the buffer,
|
||||||
|
/// or, for example, resize it for some reason. Generally, you should never need this.
|
||||||
|
///
|
||||||
|
/// ## Safety
|
||||||
|
///
|
||||||
|
/// This uses a **static mut** and we assume it will *never* be passed between threads.
|
||||||
|
/// Do not pass the raw pointer you get between threads at all -- Dear ImGui is single-threaded.
|
||||||
|
/// We otherwise make no assumptions about the size or keep state in this buffer between calls,
|
||||||
|
/// so editing the `UiBuffer` is fine.
|
||||||
|
pub unsafe fn scratch_buffer(&self) -> &cell::UnsafeCell<string::UiBuffer> {
|
||||||
|
&self.buffer
|
||||||
|
}
|
||||||
|
|
||||||
/// Internal method to push a single text to our scratch buffer.
|
/// Internal method to push a single text to our scratch buffer.
|
||||||
fn scratch_txt(&self, txt: impl AsRef<str>) -> *const sys::cty::c_char {
|
fn scratch_txt(&self, txt: impl AsRef<str>) -> *const sys::cty::c_char {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -169,43 +185,44 @@ impl<'ui> Ui<'ui> {
|
|||||||
unsafe { &*(sys::igGetIO() as *const Io) }
|
unsafe { &*(sys::igGetIO() as *const Io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an immutable reference to the font atlas
|
/// Returns an immutable reference to the font atlas.
|
||||||
pub fn fonts(&self) -> FontAtlasRef<'_> {
|
pub fn fonts(&self) -> &FontAtlas {
|
||||||
match self.font_atlas {
|
unsafe { &*(self.io().fonts as *const FontAtlas) }
|
||||||
Some(ref font_atlas) => FontAtlasRef::Shared(font_atlas),
|
|
||||||
None => unsafe {
|
|
||||||
let fonts = &*(self.io().fonts as *const FontAtlas);
|
|
||||||
FontAtlasRef::Owned(fonts)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a clone of the user interface style
|
/// Returns a clone of the user interface style
|
||||||
pub fn clone_style(&self) -> Style {
|
pub fn clone_style(&self) -> Style {
|
||||||
*self.ctx.style()
|
unsafe { *self.style() }
|
||||||
}
|
}
|
||||||
/// Renders the frame and returns a reference to the resulting draw data
|
|
||||||
#[doc(alias = "Render", alias = "GetDrawData")]
|
|
||||||
pub fn render(self) -> &'ui DrawData {
|
|
||||||
unsafe {
|
|
||||||
sys::igRender();
|
|
||||||
&*(sys::igGetDrawData() as *mut DrawData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for Ui<'a> {
|
/// This function, and the library's api, has been changed as of `0.9`!
|
||||||
#[doc(alias = "EndFrame")]
|
/// Do not use this function! Instead, use [`Context::render`],
|
||||||
fn drop(&mut self) {
|
/// which does what this function in `0.8` used to do.
|
||||||
if !std::thread::panicking() {
|
///
|
||||||
unsafe {
|
/// This function right now simply **ends** the current frame, but does not
|
||||||
sys::igEndFrame();
|
/// return draw data. If you want to end the frame without generated draw data,
|
||||||
}
|
/// and thus save some CPU time, use [`end_frame_early`].
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.9.0",
|
||||||
|
note = "use `Context::render` to render frames, or `end_frame_early` to not render at all"
|
||||||
|
)]
|
||||||
|
pub fn render(&mut self) {
|
||||||
|
self.end_frame_early();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use this function to end the frame early.
|
||||||
|
/// After this call, you should **stop using the `Ui` object till `new_frame` has been called.**
|
||||||
|
///
|
||||||
|
/// You probably *don't want this function.* If you want to render your data, use `Context::render` now.
|
||||||
|
pub fn end_frame_early(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
sys::igEndFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Demo, debug, information
|
/// # Demo, debug, information
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Renders a demo window (previously called a test window), which demonstrates most
|
/// Renders a demo window (previously called a test window), which demonstrates most
|
||||||
/// Dear Imgui features.
|
/// Dear Imgui features.
|
||||||
#[doc(alias = "ShowDemoWindow")]
|
#[doc(alias = "ShowDemoWindow")]
|
||||||
@ -316,7 +333,7 @@ impl<'a> Default for Id<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// # Windows
|
/// # Windows
|
||||||
/// Start constructing a window.
|
/// Start constructing a window.
|
||||||
///
|
///
|
||||||
@ -338,7 +355,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// ui.text("An example");
|
/// ui.text("An example");
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn window<Label: AsRef<str>>(&'ui self, name: Label) -> Window<'ui, '_, Label> {
|
pub fn window<Label: AsRef<str>>(&self, name: Label) -> Window<'_, '_, Label> {
|
||||||
Window::new(self, name)
|
Window::new(self, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,13 +374,13 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// wt.unwrap().end()
|
/// wt.unwrap().end()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn child_window<Label: AsRef<str>>(&'ui self, name: Label) -> ChildWindow<'ui, Label> {
|
pub fn child_window<Label: AsRef<str>>(&self, name: Label) -> ChildWindow<'_, Label> {
|
||||||
ChildWindow::new(self, name)
|
ChildWindow::new(self, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Widgets: Input
|
// Widgets: Input
|
||||||
impl<'ui> Ui<'ui> {
|
impl<'ui> Ui {
|
||||||
#[doc(alias = "InputText", alias = "InputTextWithHint")]
|
#[doc(alias = "InputText", alias = "InputTextWithHint")]
|
||||||
pub fn input_text<'p, L: AsRef<str>>(
|
pub fn input_text<'p, L: AsRef<str>>(
|
||||||
&'ui self,
|
&'ui self,
|
||||||
@ -475,7 +492,7 @@ create_token!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// # Tooltips
|
/// # Tooltips
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Construct a tooltip window that can have any kind of content.
|
/// Construct a tooltip window that can have any kind of content.
|
||||||
///
|
///
|
||||||
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
|
/// Typically used with `Ui::is_item_hovered()` or some other conditional check.
|
||||||
@ -542,7 +559,7 @@ create_token!(
|
|||||||
/// imgui can disable widgets so they don't react to mouse/keyboard
|
/// imgui can disable widgets so they don't react to mouse/keyboard
|
||||||
/// inputs, and are displayed differently (currently dimmed by an
|
/// inputs, and are displayed differently (currently dimmed by an
|
||||||
/// amount set in [`Style::disabled_alpha`])
|
/// amount set in [`Style::disabled_alpha`])
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Creates a scope where interactions are disabled.
|
/// Creates a scope where interactions are disabled.
|
||||||
///
|
///
|
||||||
/// Scope ends when returned token is dropped, or `.end()` is
|
/// Scope ends when returned token is dropped, or `.end()` is
|
||||||
@ -604,7 +621,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Widgets: ListBox
|
// Widgets: ListBox
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
#[doc(alias = "ListBox")]
|
#[doc(alias = "ListBox")]
|
||||||
pub fn list_box<'p, StringType: AsRef<str> + ?Sized>(
|
pub fn list_box<'p, StringType: AsRef<str> + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
@ -614,7 +631,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
height_in_items: i32,
|
height_in_items: i32,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (label_ptr, items_inner) = unsafe {
|
let (label_ptr, items_inner) = unsafe {
|
||||||
let handle = &mut *self.buffer.get();
|
let handle = &mut *self.scratch_buffer().get();
|
||||||
|
|
||||||
handle.refresh_buffer();
|
handle.refresh_buffer();
|
||||||
let label_ptr = handle.push(label);
|
let label_ptr = handle.push(label);
|
||||||
@ -671,7 +688,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
impl<'ui> Ui {
|
||||||
#[doc(alias = "PlotLines")]
|
#[doc(alias = "PlotLines")]
|
||||||
pub fn plot_lines<'p, Label: AsRef<str>>(
|
pub fn plot_lines<'p, Label: AsRef<str>>(
|
||||||
&'ui self,
|
&'ui self,
|
||||||
@ -680,9 +697,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
) -> PlotLines<'ui, 'p, Label> {
|
) -> PlotLines<'ui, 'p, Label> {
|
||||||
PlotLines::new(self, label, values)
|
PlotLines::new(self, label, values)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
|
||||||
#[doc(alias = "PlotHistogram")]
|
#[doc(alias = "PlotHistogram")]
|
||||||
pub fn plot_histogram<'p, Label: AsRef<str>>(
|
pub fn plot_histogram<'p, Label: AsRef<str>>(
|
||||||
&'ui self,
|
&'ui self,
|
||||||
@ -691,9 +706,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
) -> PlotHistogram<'ui, 'p, Label> {
|
) -> PlotHistogram<'ui, 'p, Label> {
|
||||||
PlotHistogram::new(self, label, values)
|
PlotHistogram::new(self, label, values)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
|
||||||
/// Calculate the size required for a given text string.
|
/// Calculate the size required for a given text string.
|
||||||
///
|
///
|
||||||
/// This is the same as [calc_text_size_with_opts](Self::calc_text_size_with_opts)
|
/// This is the same as [calc_text_size_with_opts](Self::calc_text_size_with_opts)
|
||||||
@ -736,7 +749,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Draw list for custom drawing
|
/// # Draw list for custom drawing
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Get access to drawing API
|
/// Get access to drawing API
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -768,19 +781,19 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[doc(alias = "GetWindowDrawList")]
|
#[doc(alias = "GetWindowDrawList")]
|
||||||
pub fn get_window_draw_list(&'ui self) -> DrawListMut<'ui> {
|
pub fn get_window_draw_list(&self) -> DrawListMut<'_> {
|
||||||
DrawListMut::window(self)
|
DrawListMut::window(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[doc(alias = "GetBackgroundDrawList")]
|
#[doc(alias = "GetBackgroundDrawList")]
|
||||||
pub fn get_background_draw_list(&'ui self) -> DrawListMut<'ui> {
|
pub fn get_background_draw_list(&self) -> DrawListMut<'_> {
|
||||||
DrawListMut::background(self)
|
DrawListMut::background(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[doc(alias = "GetForegroundDrawList")]
|
#[doc(alias = "GetForegroundDrawList")]
|
||||||
pub fn get_foreground_draw_list(&'ui self) -> DrawListMut<'ui> {
|
pub fn get_foreground_draw_list(&self) -> DrawListMut<'_> {
|
||||||
DrawListMut::foreground(self)
|
DrawListMut::foreground(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ impl ListClipper {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> ListClipperToken<'ui> {
|
pub fn begin(self, ui: &Ui) -> ListClipperToken<'_> {
|
||||||
let list_clipper = unsafe {
|
let list_clipper = unsafe {
|
||||||
let list_clipper = sys::ImGuiListClipper_ImGuiListClipper();
|
let list_clipper = sys::ImGuiListClipper_ImGuiListClipper();
|
||||||
sys::ImGuiListClipper_Begin(list_clipper, self.items_count, self.items_height);
|
sys::ImGuiListClipper_Begin(list_clipper, self.items_count, self.items_height);
|
||||||
@ -34,11 +34,11 @@ impl ListClipper {
|
|||||||
|
|
||||||
pub struct ListClipperToken<'ui> {
|
pub struct ListClipperToken<'ui> {
|
||||||
list_clipper: *mut sys::ImGuiListClipper,
|
list_clipper: *mut sys::ImGuiListClipper,
|
||||||
_phantom: PhantomData<&'ui Ui<'ui>>,
|
_phantom: PhantomData<&'ui Ui>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> ListClipperToken<'ui> {
|
impl<'ui> ListClipperToken<'ui> {
|
||||||
fn new(_: &Ui<'ui>, list_clipper: *mut sys::ImGuiListClipper) -> Self {
|
fn new(_: &Ui, list_clipper: *mut sys::ImGuiListClipper) -> Self {
|
||||||
Self {
|
Self {
|
||||||
list_clipper,
|
list_clipper,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
|
|||||||
@ -12,11 +12,11 @@ pub struct PlotHistogram<'ui, 'p, Label, Overlay = &'static str> {
|
|||||||
scale_min: f32,
|
scale_min: f32,
|
||||||
scale_max: f32,
|
scale_max: f32,
|
||||||
graph_size: [f32; 2],
|
graph_size: [f32; 2],
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, Label: AsRef<str>> PlotHistogram<'ui, 'p, Label> {
|
impl<'ui, 'p, Label: AsRef<str>> PlotHistogram<'ui, 'p, Label> {
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self {
|
pub fn new(ui: &'ui Ui, label: Label, values: &'p [f32]) -> Self {
|
||||||
PlotHistogram {
|
PlotHistogram {
|
||||||
label,
|
label,
|
||||||
values,
|
values,
|
||||||
|
|||||||
@ -12,11 +12,11 @@ pub struct PlotLines<'ui, 'p, Label, Overlay = &'static str> {
|
|||||||
scale_min: f32,
|
scale_min: f32,
|
||||||
scale_max: f32,
|
scale_max: f32,
|
||||||
graph_size: [f32; 2],
|
graph_size: [f32; 2],
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, Label: AsRef<str>> PlotLines<'ui, 'p, Label> {
|
impl<'ui, 'p, Label: AsRef<str>> PlotLines<'ui, 'p, Label> {
|
||||||
pub fn new(ui: &'ui Ui<'ui>, label: Label, values: &'p [f32]) -> Self {
|
pub fn new(ui: &'ui Ui, label: Label, values: &'p [f32]) -> Self {
|
||||||
PlotLines {
|
PlotLines {
|
||||||
label,
|
label,
|
||||||
values,
|
values,
|
||||||
|
|||||||
@ -118,7 +118,7 @@ impl<'p, Label: AsRef<str>> PopupModal<'p, Label> {
|
|||||||
/// Consume and draw the PopupModal.
|
/// Consume and draw the PopupModal.
|
||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
#[doc(alias = "BeginPopupModal")]
|
#[doc(alias = "BeginPopupModal")]
|
||||||
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui<'_>, f: F) -> Option<T> {
|
pub fn build<T, F: FnOnce() -> T>(self, ui: &Ui, f: F) -> Option<T> {
|
||||||
self.begin_popup(ui).map(|_popup| f())
|
self.begin_popup(ui).map(|_popup| f())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ impl<'p, Label: AsRef<str>> PopupModal<'p, Label> {
|
|||||||
/// This should be called *per frame*, whereas [`Ui::open_popup`]
|
/// This should be called *per frame*, whereas [`Ui::open_popup`]
|
||||||
/// should be called *once* when you want to actual create the popup.
|
/// should be called *once* when you want to actual create the popup.
|
||||||
#[doc(alias = "BeginPopupModal")]
|
#[doc(alias = "BeginPopupModal")]
|
||||||
pub fn begin_popup<'ui>(self, ui: &Ui<'ui>) -> Option<PopupToken<'ui>> {
|
pub fn begin_popup(self, ui: &Ui) -> Option<PopupToken<'_>> {
|
||||||
let render = unsafe {
|
let render = unsafe {
|
||||||
sys::igBeginPopupModal(
|
sys::igBeginPopupModal(
|
||||||
ui.scratch_txt(self.label),
|
ui.scratch_txt(self.label),
|
||||||
@ -148,7 +148,7 @@ impl<'p, Label: AsRef<str>> PopupModal<'p, Label> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Widgets: Popups
|
// Widgets: Popups
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Instructs ImGui to open a popup, which must be began with either [`begin_popup`](Self::begin_popup)
|
/// Instructs ImGui to open a popup, which must be began with either [`begin_popup`](Self::begin_popup)
|
||||||
/// or [`popup`](Self::popup). You also use this function to begin [PopupModal].
|
/// or [`popup`](Self::popup). You also use this function to begin [PopupModal].
|
||||||
///
|
///
|
||||||
|
|||||||
@ -1,17 +1,14 @@
|
|||||||
use std::mem;
|
|
||||||
use std::os::raw::{c_char, c_void};
|
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::fonts::atlas::FontId;
|
use crate::fonts::atlas::FontId;
|
||||||
use crate::internal::RawCast;
|
use crate::internal::RawCast;
|
||||||
use crate::math::MintVec4;
|
use crate::math::MintVec4;
|
||||||
use crate::style::{StyleColor, StyleVar};
|
use crate::style::{StyleColor, StyleVar};
|
||||||
use crate::sys;
|
use crate::sys;
|
||||||
use crate::{Id, Ui};
|
use crate::{Id, Ui};
|
||||||
|
use std::mem;
|
||||||
|
use std::os::raw::{c_char, c_void};
|
||||||
|
|
||||||
/// # Parameter stacks (shared)
|
/// # Parameter stacks (shared)
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Switches to the given font by pushing it to the font stack.
|
/// Switches to the given font by pushing it to the font stack.
|
||||||
///
|
///
|
||||||
/// Returns a `FontStackToken` that must be popped by calling `.pop()`
|
/// Returns a `FontStackToken` that must be popped by calling `.pop()`
|
||||||
@ -180,7 +177,7 @@ unsafe fn push_style_var(style_var: StyleVar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Parameter stacks (current window)
|
/// # Parameter stacks (current window)
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Changes the item width by pushing a change to the item width stack.
|
/// Changes the item width by pushing a change to the item width stack.
|
||||||
///
|
///
|
||||||
/// Returns an `ItemWidthStackToken` that may be popped by calling `.pop()`
|
/// Returns an `ItemWidthStackToken` that may be popped by calling `.pop()`
|
||||||
@ -190,9 +187,9 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// - `< 0.0`: `item_width` pixels relative to the right of window (-1.0 always aligns width to
|
/// - `< 0.0`: `item_width` pixels relative to the right of window (-1.0 always aligns width to
|
||||||
/// the right side)
|
/// the right side)
|
||||||
#[doc(alias = "PushItemWith")]
|
#[doc(alias = "PushItemWith")]
|
||||||
pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken {
|
pub fn push_item_width(&self, item_width: f32) -> ItemWidthStackToken<'_> {
|
||||||
unsafe { sys::igPushItemWidth(item_width) };
|
unsafe { sys::igPushItemWidth(item_width) };
|
||||||
ItemWidthStackToken { _ctx: self.ctx }
|
ItemWidthStackToken::new(self)
|
||||||
}
|
}
|
||||||
/// Sets the width of the next item.
|
/// Sets the width of the next item.
|
||||||
///
|
///
|
||||||
@ -220,7 +217,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
///
|
///
|
||||||
/// Returns a `TextWrapPosStackToken` that may be popped by calling `.pop()`
|
/// Returns a `TextWrapPosStackToken` that may be popped by calling `.pop()`
|
||||||
#[doc(alias = "PushTextWrapPos")]
|
#[doc(alias = "PushTextWrapPos")]
|
||||||
pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken {
|
pub fn push_text_wrap_pos(&self) -> TextWrapPosStackToken<'_> {
|
||||||
self.push_text_wrap_pos_with_pos(0.0)
|
self.push_text_wrap_pos_with_pos(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,25 +229,58 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// - `= 0.0`: wrap to end of window (or column)
|
/// - `= 0.0`: wrap to end of window (or column)
|
||||||
/// - `< 0.0`: no wrapping
|
/// - `< 0.0`: no wrapping
|
||||||
#[doc(alias = "PushTextWrapPos")]
|
#[doc(alias = "PushTextWrapPos")]
|
||||||
pub fn push_text_wrap_pos_with_pos(&self, wrap_pos_x: f32) -> TextWrapPosStackToken {
|
pub fn push_text_wrap_pos_with_pos(&self, wrap_pos_x: f32) -> TextWrapPosStackToken<'_> {
|
||||||
unsafe { sys::igPushTextWrapPos(wrap_pos_x) };
|
unsafe { sys::igPushTextWrapPos(wrap_pos_x) };
|
||||||
TextWrapPosStackToken { _ctx: self.ctx }
|
TextWrapPosStackToken::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tab stop enable.
|
||||||
|
/// Allow focusing using TAB/Shift-TAB, enabled by default but you can
|
||||||
|
/// disable it for certain widgets
|
||||||
|
///
|
||||||
|
/// Returns a [PushAllowKeyboardFocusToken] that should be dropped.
|
||||||
|
#[doc(alias = "PushAllowKeyboardFocus")]
|
||||||
|
pub fn push_allow_keyboard_focus(&self, allow: bool) -> PushAllowKeyboardFocusToken<'_> {
|
||||||
|
unsafe { sys::igPushAllowKeyboardFocus(allow) };
|
||||||
|
PushAllowKeyboardFocusToken::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// In 'repeat' mode, button_x functions return repeated true in a typematic
|
||||||
|
/// manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting).
|
||||||
|
/// Note that you can call IsItemActive() after any Button() to tell if the
|
||||||
|
/// button is held in the current frame.
|
||||||
|
///
|
||||||
|
/// Returns a [PushButtonRepeatToken] that should be dropped.
|
||||||
|
#[doc(alias = "PushAllowKeyboardFocus")]
|
||||||
|
pub fn push_button_repeat(&self, allow: bool) -> PushButtonRepeatToken<'_> {
|
||||||
|
unsafe { sys::igPushButtonRepeat(allow) };
|
||||||
|
PushButtonRepeatToken::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes an item flag by pushing a change to the item flag stack.
|
/// Changes an item flag by pushing a change to the item flag stack.
|
||||||
///
|
///
|
||||||
/// Returns a `ItemFlagsStackToken` that may be popped by calling `.pop()`
|
/// Returns a `ItemFlagsStackToken` that may be popped by calling `.pop()`
|
||||||
#[doc(alias = "PushItemFlag")]
|
///
|
||||||
pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken {
|
/// ## Deprecated
|
||||||
|
///
|
||||||
|
/// This was deprecated in `0.9.0` because it isn't part of the dear imgui design,
|
||||||
|
/// and supporting it required a manual implementation of its drop token.
|
||||||
|
///
|
||||||
|
/// Instead, just use [`push_allow_keyboard_focus`] and [`push_button_repeat`].
|
||||||
|
///
|
||||||
|
/// [`push_allow_keyboard_focus`]: Self::push_allow_keyboard_focus
|
||||||
|
/// [`push_button_repeat`]: Self::push_button_repeat
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.9.0",
|
||||||
|
note = "use `push_allow_keyboard_focus` or `push_button_repeat` instead"
|
||||||
|
)]
|
||||||
|
pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken<'_> {
|
||||||
use self::ItemFlag::*;
|
use self::ItemFlag::*;
|
||||||
match item_flag {
|
match item_flag {
|
||||||
AllowKeyboardFocus(v) => unsafe { sys::igPushAllowKeyboardFocus(v) },
|
AllowKeyboardFocus(v) => unsafe { sys::igPushAllowKeyboardFocus(v) },
|
||||||
ButtonRepeat(v) => unsafe { sys::igPushButtonRepeat(v) },
|
ButtonRepeat(v) => unsafe { sys::igPushButtonRepeat(v) },
|
||||||
}
|
}
|
||||||
ItemFlagsStackToken {
|
ItemFlagsStackToken::new(self, item_flag)
|
||||||
discriminant: mem::discriminant(&item_flag),
|
|
||||||
_ctx: self.ctx,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,54 +291,78 @@ pub enum ItemFlag {
|
|||||||
ButtonRepeat(bool),
|
ButtonRepeat(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ItemWidthStackToken {
|
create_token!(
|
||||||
_ctx: *const Context,
|
/// Tracks a window that can be ended by calling `.end()`
|
||||||
}
|
/// or by dropping.
|
||||||
|
pub struct ItemWidthStackToken<'ui>;
|
||||||
|
|
||||||
impl ItemWidthStackToken {
|
/// Ends a window
|
||||||
/// Pops a change from the item width stack
|
|
||||||
#[doc(alias = "PopItemWidth")]
|
#[doc(alias = "PopItemWidth")]
|
||||||
pub fn pop(mut self, _: &Ui<'_>) {
|
drop { sys::igPopItemWidth() }
|
||||||
self._ctx = ptr::null();
|
);
|
||||||
unsafe { sys::igPopItemWidth() };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tracks a change pushed to the text wrap position stack
|
create_token!(
|
||||||
pub struct TextWrapPosStackToken {
|
/// Tracks a window that can be ended by calling `.end()`
|
||||||
_ctx: *const Context,
|
/// or by dropping.
|
||||||
}
|
pub struct TextWrapPosStackToken<'ui>;
|
||||||
|
|
||||||
impl TextWrapPosStackToken {
|
/// Ends a window
|
||||||
/// Pops a change from the text wrap position stack
|
|
||||||
#[doc(alias = "PopTextWrapPos")]
|
#[doc(alias = "PopTextWrapPos")]
|
||||||
pub fn pop(mut self, _: &Ui<'_>) {
|
drop { sys::igPopTextWrapPos() }
|
||||||
self._ctx = ptr::null();
|
);
|
||||||
unsafe { sys::igPopTextWrapPos() };
|
|
||||||
|
create_token!(
|
||||||
|
/// Tracks a window that can be ended by calling `.end()`
|
||||||
|
/// or by dropping.
|
||||||
|
pub struct PushAllowKeyboardFocusToken<'ui>;
|
||||||
|
|
||||||
|
/// Ends a window
|
||||||
|
#[doc(alias = "PopAllowKeyboardFocus")]
|
||||||
|
drop { sys::igPopAllowKeyboardFocus() }
|
||||||
|
);
|
||||||
|
|
||||||
|
create_token!(
|
||||||
|
/// Tracks a window that can be ended by calling `.end()`
|
||||||
|
/// or by dropping.
|
||||||
|
pub struct PushButtonRepeatToken<'ui>;
|
||||||
|
|
||||||
|
/// Ends a window
|
||||||
|
#[doc(alias = "PopButtonRepeat")]
|
||||||
|
drop { sys::igPopButtonRepeat() }
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Tracks a change pushed to the item flags stack.
|
||||||
|
///
|
||||||
|
/// The "item flags" stack was a concept invented in imgui-rs that doesn't have an
|
||||||
|
/// ImGui equivalent. We're phasing these out to make imgui-rs feel simpler to use.
|
||||||
|
#[must_use]
|
||||||
|
pub struct ItemFlagsStackToken<'a>(
|
||||||
|
std::marker::PhantomData<&'a Ui>,
|
||||||
|
mem::Discriminant<ItemFlag>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<'a> ItemFlagsStackToken<'a> {
|
||||||
|
/// Creates a new token type.
|
||||||
|
pub(crate) fn new(_: &'a crate::Ui, kind: ItemFlag) -> Self {
|
||||||
|
Self(std::marker::PhantomData, mem::discriminant(&kind))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn end(self) {
|
||||||
|
// left empty for drop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracks a change pushed to the item flags stack
|
impl Drop for ItemFlagsStackToken<'_> {
|
||||||
pub struct ItemFlagsStackToken {
|
fn drop(&mut self) {
|
||||||
discriminant: mem::Discriminant<ItemFlag>,
|
unsafe {
|
||||||
_ctx: *const Context,
|
if self.1 == mem::discriminant(&ItemFlag::AllowKeyboardFocus(true)) {
|
||||||
}
|
sys::igPopAllowKeyboardFocus();
|
||||||
|
} else if self.1 == mem::discriminant(&ItemFlag::ButtonRepeat(true)) {
|
||||||
impl ItemFlagsStackToken {
|
sys::igPopButtonRepeat();
|
||||||
/// Pops a change from the item flags stack
|
} else {
|
||||||
|
unreachable!();
|
||||||
#[doc(alias = "PopAllowKeyboardFocus", alias = "PopButtonRepeat")]
|
}
|
||||||
pub fn pop(mut self, _: &Ui<'_>) {
|
|
||||||
self._ctx = ptr::null();
|
|
||||||
const ALLOW_KEYBOARD_FOCUS: ItemFlag = ItemFlag::AllowKeyboardFocus(true);
|
|
||||||
const BUTTON_REPEAT: ItemFlag = ItemFlag::ButtonRepeat(true);
|
|
||||||
|
|
||||||
if self.discriminant == mem::discriminant(&ALLOW_KEYBOARD_FOCUS) {
|
|
||||||
unsafe { sys::igPopAllowKeyboardFocus() };
|
|
||||||
} else if self.discriminant == mem::discriminant(&BUTTON_REPEAT) {
|
|
||||||
unsafe { sys::igPopButtonRepeat() };
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +384,7 @@ impl IdStackToken<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # ID stack
|
/// # ID stack
|
||||||
impl<'ui> Ui<'ui> {
|
impl<'ui> Ui {
|
||||||
/// Pushes an identifier to the ID stack.
|
/// Pushes an identifier to the ID stack.
|
||||||
/// This can be called with an integer, a string, or a pointer.
|
/// This can be called with an integer, a string, or a pointer.
|
||||||
///
|
///
|
||||||
@ -408,7 +462,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
#[doc(alias = "PushId")]
|
#[doc(alias = "PushId")]
|
||||||
pub fn push_id<'a, I: Into<Id<'a>>>(&self, id: I) -> IdStackToken<'ui> {
|
pub fn push_id<'a, I: Into<Id<'a>>>(&'ui self, id: I) -> IdStackToken<'ui> {
|
||||||
let id = id.into();
|
let id = id.into();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@ -7,16 +7,16 @@ use std::{fmt, ptr};
|
|||||||
|
|
||||||
/// this is the unsafe cell upon which we build our abstraction.
|
/// this is the unsafe cell upon which we build our abstraction.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct UiBuffer {
|
pub struct UiBuffer {
|
||||||
buffer: Vec<u8>,
|
pub buffer: Vec<u8>,
|
||||||
max_len: usize,
|
pub max_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiBuffer {
|
impl UiBuffer {
|
||||||
/// Creates a new max buffer with the given length.
|
/// Creates a new max buffer with the given length.
|
||||||
pub fn new(max_len: usize) -> Self {
|
pub const fn new(max_len: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
buffer: Vec::with_capacity(max_len),
|
buffer: Vec::new(),
|
||||||
max_len,
|
max_len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -249,7 +249,7 @@ pub enum TableSortDirection {
|
|||||||
Descending,
|
Descending,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Begins a table with no flags and with standard sizing contraints.
|
/// Begins a table with no flags and with standard sizing contraints.
|
||||||
///
|
///
|
||||||
/// This does no work on styling the headers (the top row) -- see either
|
/// This does no work on styling the headers (the top row) -- see either
|
||||||
@ -263,7 +263,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
&self,
|
&self,
|
||||||
str_id: impl AsRef<str>,
|
str_id: impl AsRef<str>,
|
||||||
column_count: usize,
|
column_count: usize,
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
self.begin_table_with_flags(str_id, column_count, TableFlags::empty())
|
self.begin_table_with_flags(str_id, column_count, TableFlags::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
str_id: impl AsRef<str>,
|
str_id: impl AsRef<str>,
|
||||||
column_count: usize,
|
column_count: usize,
|
||||||
flags: TableFlags,
|
flags: TableFlags,
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
self.begin_table_with_sizing(str_id, column_count, flags, [0.0, 0.0], 0.0)
|
self.begin_table_with_sizing(str_id, column_count, flags, [0.0, 0.0], 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
flags: TableFlags,
|
flags: TableFlags,
|
||||||
outer_size: [f32; 2],
|
outer_size: [f32; 2],
|
||||||
inner_width: f32,
|
inner_width: f32,
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igBeginTable(
|
sys::igBeginTable(
|
||||||
self.scratch_txt(str_id),
|
self.scratch_txt(str_id),
|
||||||
@ -324,7 +324,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
&self,
|
&self,
|
||||||
str_id: impl AsRef<str>,
|
str_id: impl AsRef<str>,
|
||||||
column_data: [TableColumnSetup<'a, Name>; N],
|
column_data: [TableColumnSetup<'a, Name>; N],
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
self.begin_table_header_with_flags(str_id, column_data, TableFlags::empty())
|
self.begin_table_header_with_flags(str_id, column_data, TableFlags::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
str_id: impl AsRef<str>,
|
str_id: impl AsRef<str>,
|
||||||
column_data: [TableColumnSetup<'a, Name>; N],
|
column_data: [TableColumnSetup<'a, Name>; N],
|
||||||
flags: TableFlags,
|
flags: TableFlags,
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
self.begin_table_header_with_sizing(str_id, column_data, flags, [0.0, 0.0], 0.0)
|
self.begin_table_header_with_sizing(str_id, column_data, flags, [0.0, 0.0], 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
flags: TableFlags,
|
flags: TableFlags,
|
||||||
outer_size: [f32; 2],
|
outer_size: [f32; 2],
|
||||||
inner_width: f32,
|
inner_width: f32,
|
||||||
) -> Option<TableToken<'ui>> {
|
) -> Option<TableToken<'_>> {
|
||||||
self.begin_table_with_sizing(str_id, N, flags, outer_size, inner_width)
|
self.begin_table_with_sizing(str_id, N, flags, outer_size, inner_width)
|
||||||
.map(|data| {
|
.map(|data| {
|
||||||
for value in column_data {
|
for value in column_data {
|
||||||
@ -769,7 +769,7 @@ impl<'a, Name: AsRef<str>> TableColumnSetup<'a, Name> {
|
|||||||
/// [should_sort]: Self::should_sort
|
/// [should_sort]: Self::should_sort
|
||||||
/// [specs]: Self::specs
|
/// [specs]: Self::specs
|
||||||
/// [set_sorted]: Self::set_sorted
|
/// [set_sorted]: Self::set_sorted
|
||||||
pub struct TableSortSpecsMut<'ui>(*mut sys::ImGuiTableSortSpecs, PhantomData<Ui<'ui>>);
|
pub struct TableSortSpecsMut<'ui>(*mut sys::ImGuiTableSortSpecs, PhantomData<&'ui Ui>);
|
||||||
|
|
||||||
impl TableSortSpecsMut<'_> {
|
impl TableSortSpecsMut<'_> {
|
||||||
/// Gets the specs for a given sort. In most scenarios, this will be a slice of 1 entry.
|
/// Gets the specs for a given sort. In most scenarios, this will be a slice of 1 entry.
|
||||||
|
|||||||
@ -19,11 +19,11 @@ macro_rules! create_token {
|
|||||||
) => {
|
) => {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
$(#[$struct_meta])*
|
$(#[$struct_meta])*
|
||||||
pub struct $token_name<'a>($crate::__core::marker::PhantomData<crate::Ui<'a>>);
|
pub struct $token_name<'a>($crate::__core::marker::PhantomData<&'a crate::Ui>);
|
||||||
|
|
||||||
impl<'a> $token_name<'a> {
|
impl<'a> $token_name<'a> {
|
||||||
/// Creates a new token type.
|
/// Creates a new token type.
|
||||||
pub(crate) fn new(_: &crate::Ui<'a>) -> Self {
|
pub(crate) fn new(_: &'a crate::Ui) -> Self {
|
||||||
Self(std::marker::PhantomData)
|
Self(std::marker::PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Item/widget utilities
|
/// # Item/widget utilities
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns `true` if the last item is hovered
|
/// Returns `true` if the last item is hovered
|
||||||
#[doc(alias = "IsItemHovered")]
|
#[doc(alias = "IsItemHovered")]
|
||||||
pub fn is_item_hovered(&self) -> bool {
|
pub fn is_item_hovered(&self) -> bool {
|
||||||
@ -142,7 +142,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Miscellaneous utilities
|
/// # Miscellaneous utilities
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns `true` if the rectangle (of given size, starting from cursor position) is visible
|
/// Returns `true` if the rectangle (of given size, starting from cursor position) is visible
|
||||||
#[doc(alias = "IsRectVisibleNil")]
|
#[doc(alias = "IsRectVisibleNil")]
|
||||||
pub fn is_cursor_rect_visible(&self, size: impl Into<MintVec2>) -> bool {
|
pub fn is_cursor_rect_visible(&self, size: impl Into<MintVec2>) -> bool {
|
||||||
@ -177,7 +177,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// style object.
|
/// style object.
|
||||||
#[doc(alias = "GetStyle")]
|
#[doc(alias = "GetStyle")]
|
||||||
pub fn style_color(&self, style_color: StyleColor) -> [f32; 4] {
|
pub fn style_color(&self, style_color: StyleColor) -> [f32; 4] {
|
||||||
self.ctx.style()[style_color]
|
unsafe { self.style() }.colors[style_color as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a shared reference to the current [`Style`].
|
/// Returns a shared reference to the current [`Style`].
|
||||||
@ -193,6 +193,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// pop. The [`clone_style`](Ui::clone_style) version may instead be used to avoid `unsafe`.
|
/// pop. The [`clone_style`](Ui::clone_style) version may instead be used to avoid `unsafe`.
|
||||||
#[doc(alias = "GetStyle")]
|
#[doc(alias = "GetStyle")]
|
||||||
pub unsafe fn style(&self) -> &Style {
|
pub unsafe fn style(&self) -> &Style {
|
||||||
self.ctx.style()
|
// safe because Style is a transparent wrapper around sys::ImGuiStyle
|
||||||
|
&*(sys::igGetStyle() as *const Style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -326,7 +326,7 @@ where
|
|||||||
/// Builds the color editor.
|
/// Builds the color editor.
|
||||||
///
|
///
|
||||||
/// Returns true if the color value was changed.
|
/// Returns true if the color value was changed.
|
||||||
pub fn build(mut self, ui: &Ui<'_>) -> bool {
|
pub fn build(mut self, ui: &Ui) -> bool {
|
||||||
// if let EditableColor::Float3(_) = self.value {
|
// if let EditableColor::Float3(_) = self.value {
|
||||||
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ where
|
|||||||
/// Builds the color editor.
|
/// Builds the color editor.
|
||||||
///
|
///
|
||||||
/// Returns true if the color value was changed.
|
/// Returns true if the color value was changed.
|
||||||
pub fn build(self, ui: &Ui<'_>) -> bool {
|
pub fn build(self, ui: &Ui) -> bool {
|
||||||
let as_vec4: MintVec4 = (*self.value).into();
|
let as_vec4: MintVec4 = (*self.value).into();
|
||||||
let mut as_vec4: [f32; 4] = as_vec4.into();
|
let mut as_vec4: [f32; 4] = as_vec4.into();
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ where
|
|||||||
/// Builds the color picker.
|
/// Builds the color picker.
|
||||||
///
|
///
|
||||||
/// Returns true if the color value was changed.
|
/// Returns true if the color value was changed.
|
||||||
pub fn build(mut self, ui: &Ui<'_>) -> bool {
|
pub fn build(mut self, ui: &Ui) -> bool {
|
||||||
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
||||||
let mut value: [f32; 3] = (*self.value).into().into();
|
let mut value: [f32; 3] = (*self.value).into().into();
|
||||||
let changed = unsafe {
|
let changed = unsafe {
|
||||||
@ -886,7 +886,7 @@ where
|
|||||||
/// Builds the color picker.
|
/// Builds the color picker.
|
||||||
///
|
///
|
||||||
/// Returns true if the color value was changed.
|
/// Returns true if the color value was changed.
|
||||||
pub fn build(mut self, ui: &Ui<'_>) -> bool {
|
pub fn build(mut self, ui: &Ui) -> bool {
|
||||||
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
self.flags.insert(ColorEditFlags::NO_ALPHA);
|
||||||
let mut value: [f32; 4] = (*self.value).into().into();
|
let mut value: [f32; 4] = (*self.value).into().into();
|
||||||
let ref_color = self.ref_color.map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
let ref_color = self.ref_color.map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||||
@ -1009,7 +1009,7 @@ impl<T: AsRef<str>> ColorButton<T> {
|
|||||||
/// Builds the color button.
|
/// Builds the color button.
|
||||||
///
|
///
|
||||||
/// Returns true if this color button was clicked.
|
/// Returns true if this color button was clicked.
|
||||||
pub fn build(self, ui: &Ui<'_>) -> bool {
|
pub fn build(self, ui: &Ui) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igColorButton(
|
sys::igColorButton(
|
||||||
ui.scratch_txt(self.desc_id),
|
ui.scratch_txt(self.desc_id),
|
||||||
@ -1022,7 +1022,7 @@ impl<T: AsRef<str>> ColorButton<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Widgets: Color Editor/Picker
|
/// # Widgets: Color Editor/Picker
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Initializes current color editor/picker options (generally on application startup) if you
|
/// Initializes current color editor/picker options (generally on application startup) if you
|
||||||
/// want to select a default format, picker type, etc. Users will be able to change many
|
/// want to select a default format, picker type, etc. Users will be able to change many
|
||||||
/// settings, unless you use .options(false) in your widget builders.
|
/// settings, unless you use .options(false) in your widget builders.
|
||||||
|
|||||||
@ -142,7 +142,7 @@ impl<T: AsRef<str>, Preview: AsRef<str>> ComboBox<T, Preview> {
|
|||||||
///
|
///
|
||||||
/// Returns `None` if the combo box is not open and no content should be rendered.
|
/// Returns `None` if the combo box is not open and no content should be rendered.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<ComboBoxToken<'ui>> {
|
pub fn begin(self, ui: &Ui) -> Option<ComboBoxToken<'_>> {
|
||||||
let should_render = unsafe {
|
let should_render = unsafe {
|
||||||
if let Some(preview_value) = self.preview_value {
|
if let Some(preview_value) = self.preview_value {
|
||||||
let (ptr_one, ptr_two) = ui.scratch_txt_two(self.label, preview_value);
|
let (ptr_one, ptr_two) = ui.scratch_txt_two(self.label, preview_value);
|
||||||
@ -162,7 +162,7 @@ impl<T: AsRef<str>, Preview: AsRef<str>> ComboBox<T, Preview> {
|
|||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
///
|
///
|
||||||
/// Note: the closure is not called if the combo box is not open.
|
/// Note: the closure is not called if the combo box is not open.
|
||||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
|
||||||
self.begin(ui).map(|_combo| f())
|
self.begin(ui).map(|_combo| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ create_token!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// # Convenience functions
|
/// # Convenience functions
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Creates a combo box which can be appended to with `Selectable::new`.
|
/// Creates a combo box which can be appended to with `Selectable::new`.
|
||||||
///
|
///
|
||||||
/// If you do not want to provide a preview, use [`begin_combo_no_preview`]. If you want
|
/// If you do not want to provide a preview, use [`begin_combo_no_preview`]. If you want
|
||||||
@ -193,7 +193,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
&self,
|
&self,
|
||||||
label: impl AsRef<str>,
|
label: impl AsRef<str>,
|
||||||
preview_value: impl AsRef<str>,
|
preview_value: impl AsRef<str>,
|
||||||
) -> Option<ComboBoxToken<'ui>> {
|
) -> Option<ComboBoxToken<'_>> {
|
||||||
self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::empty())
|
self.begin_combo_with_flags(label, preview_value, ComboBoxFlags::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
label: impl AsRef<str>,
|
label: impl AsRef<str>,
|
||||||
preview_value: impl AsRef<str>,
|
preview_value: impl AsRef<str>,
|
||||||
flags: ComboBoxFlags,
|
flags: ComboBoxFlags,
|
||||||
) -> Option<ComboBoxToken<'ui>> {
|
) -> Option<ComboBoxToken<'_>> {
|
||||||
self._begin_combo(label, Some(preview_value), flags)
|
self._begin_combo(label, Some(preview_value), flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// [begin_combo_no_preview_with_flags]: Ui::begin_combo_no_preview_with_flags
|
/// [begin_combo_no_preview_with_flags]: Ui::begin_combo_no_preview_with_flags
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[doc(alias = "BeginCombo")]
|
#[doc(alias = "BeginCombo")]
|
||||||
pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'ui>> {
|
pub fn begin_combo_no_preview(&self, label: impl AsRef<str>) -> Option<ComboBoxToken<'_>> {
|
||||||
self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::empty())
|
self.begin_combo_no_preview_with_flags(label, ComboBoxFlags::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +250,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
&self,
|
&self,
|
||||||
label: impl AsRef<str>,
|
label: impl AsRef<str>,
|
||||||
flags: ComboBoxFlags,
|
flags: ComboBoxFlags,
|
||||||
) -> Option<ComboBoxToken<'ui>> {
|
) -> Option<ComboBoxToken<'_>> {
|
||||||
self._begin_combo(label, Option::<&'static str>::None, flags)
|
self._begin_combo(label, Option::<&'static str>::None, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
label: impl AsRef<str>,
|
label: impl AsRef<str>,
|
||||||
preview_value: Option<impl AsRef<str>>,
|
preview_value: Option<impl AsRef<str>>,
|
||||||
flags: ComboBoxFlags,
|
flags: ComboBoxFlags,
|
||||||
) -> Option<ComboBoxToken<'ui>> {
|
) -> Option<ComboBoxToken<'_>> {
|
||||||
let should_render = unsafe {
|
let should_render = unsafe {
|
||||||
let (ptr_one, ptr_two) = self.scratch_txt_with_opt(label, preview_value);
|
let (ptr_one, ptr_two) = self.scratch_txt_with_opt(label, preview_value);
|
||||||
sys::igBeginCombo(ptr_one, ptr_two, flags.bits() as i32)
|
sys::igBeginCombo(ptr_one, ptr_two, flags.bits() as i32)
|
||||||
|
|||||||
@ -66,7 +66,7 @@ impl<L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> Drag<T, L, F> {
|
|||||||
/// Builds a drag slider that is bound to the given value.
|
/// Builds a drag slider that is bound to the given value.
|
||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
pub fn build(self, ui: &Ui<'_>, value: &mut T) -> bool {
|
pub fn build(self, ui: &Ui, value: &mut T) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ impl<L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> Drag<T, L, F> {
|
|||||||
/// Builds a horizontal array of multiple drag sliders attached to the given slice.
|
/// Builds a horizontal array of multiple drag sliders attached to the given slice.
|
||||||
///
|
///
|
||||||
/// Returns true if any slider value was changed.
|
/// Returns true if any slider value was changed.
|
||||||
pub fn build_array(self, ui: &Ui<'_>, values: &mut [T]) -> bool {
|
pub fn build_array(self, ui: &Ui, values: &mut [T]) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||||
|
|
||||||
@ -208,14 +208,14 @@ where
|
|||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
#[doc(alias = "DragFloatRange2")]
|
#[doc(alias = "DragFloatRange2")]
|
||||||
pub fn build(self, ui: &Ui<'_>, min: &mut f32, max: &mut f32) -> bool {
|
pub fn build(self, ui: &Ui, min: &mut f32, max: &mut f32) -> bool {
|
||||||
let label;
|
let label;
|
||||||
let mut display_format = std::ptr::null();
|
let mut display_format = std::ptr::null();
|
||||||
let mut max_display_format = std::ptr::null();
|
let mut max_display_format = std::ptr::null();
|
||||||
|
|
||||||
// we do this ourselves the long way...
|
// we do this ourselves the long way...
|
||||||
unsafe {
|
unsafe {
|
||||||
let buffer = &mut *ui.buffer.get();
|
let buffer = &mut *ui.scratch_buffer().get();
|
||||||
buffer.refresh_buffer();
|
buffer.refresh_buffer();
|
||||||
|
|
||||||
label = buffer.push(self.label);
|
label = buffer.push(self.label);
|
||||||
@ -251,14 +251,14 @@ where
|
|||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
#[doc(alias = "DragIntRange2")]
|
#[doc(alias = "DragIntRange2")]
|
||||||
pub fn build(self, ui: &Ui<'_>, min: &mut i32, max: &mut i32) -> bool {
|
pub fn build(self, ui: &Ui, min: &mut i32, max: &mut i32) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let label;
|
let label;
|
||||||
let mut display_format = std::ptr::null();
|
let mut display_format = std::ptr::null();
|
||||||
let mut max_display_format = std::ptr::null();
|
let mut max_display_format = std::ptr::null();
|
||||||
|
|
||||||
// we do this ourselves the long way...
|
// we do this ourselves the long way...
|
||||||
let buffer = &mut *ui.buffer.get();
|
let buffer = &mut *ui.scratch_buffer().get();
|
||||||
buffer.refresh_buffer();
|
buffer.refresh_buffer();
|
||||||
|
|
||||||
label = buffer.push(self.label);
|
label = buffer.push(self.label);
|
||||||
|
|||||||
@ -58,7 +58,7 @@ impl Image {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Builds the image
|
/// Builds the image
|
||||||
pub fn build(self, _: &Ui<'_>) {
|
pub fn build(self, _: &Ui) {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igImage(
|
sys::igImage(
|
||||||
self.texture_id.id() as *mut c_void,
|
self.texture_id.id() as *mut c_void,
|
||||||
@ -136,7 +136,7 @@ impl ImageButton {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Builds the image button
|
/// Builds the image button
|
||||||
pub fn build(self, _: &Ui<'_>) -> bool {
|
pub fn build(self, _: &Ui) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igImageButton(
|
sys::igImageButton(
|
||||||
self.texture_id.id() as *mut c_void,
|
self.texture_id.id() as *mut c_void,
|
||||||
|
|||||||
@ -39,7 +39,7 @@ impl<T: AsRef<str>> ListBox<T> {
|
|||||||
///
|
///
|
||||||
/// Returns `None` if the list box is not open and no content should be rendered.
|
/// Returns `None` if the list box is not open and no content should be rendered.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> Option<ListBoxToken<'ui>> {
|
pub fn begin(self, ui: &Ui) -> Option<ListBoxToken<'_>> {
|
||||||
let should_render =
|
let should_render =
|
||||||
unsafe { sys::igBeginListBox(ui.scratch_txt(self.label), self.size.into()) };
|
unsafe { sys::igBeginListBox(ui.scratch_txt(self.label), self.size.into()) };
|
||||||
if should_render {
|
if should_render {
|
||||||
@ -52,7 +52,7 @@ impl<T: AsRef<str>> ListBox<T> {
|
|||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
///
|
///
|
||||||
/// Note: the closure is not called if the list box is not open.
|
/// Note: the closure is not called if the list box is not open.
|
||||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
|
||||||
self.begin(ui).map(|_list| f())
|
self.begin(ui).map(|_list| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ impl<T: AsRef<str>> ListBox<T> {
|
|||||||
/// Builds a simple list box for choosing from a slice of values
|
/// Builds a simple list box for choosing from a slice of values
|
||||||
pub fn build_simple<V, L>(
|
pub fn build_simple<V, L>(
|
||||||
self,
|
self,
|
||||||
ui: &Ui<'_>,
|
ui: &Ui,
|
||||||
current_item: &mut usize,
|
current_item: &mut usize,
|
||||||
items: &[V],
|
items: &[V],
|
||||||
label_fn: &L,
|
label_fn: &L,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::sys;
|
|||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
|
|
||||||
/// # Widgets: Menus
|
/// # Widgets: Menus
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Creates and starts appending to a full-screen menu bar.
|
/// Creates and starts appending to a full-screen menu bar.
|
||||||
///
|
///
|
||||||
/// Returns `Some(MainMenuBarToken)` if the menu bar is visible. After content has been
|
/// Returns `Some(MainMenuBarToken)` if the menu bar is visible. After content has been
|
||||||
@ -12,7 +12,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
/// Returns `None` if the menu bar is not visible and no content should be rendered.
|
/// Returns `None` if the menu bar is not visible and no content should be rendered.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[doc(alias = "BeginMainMenuBar")]
|
#[doc(alias = "BeginMainMenuBar")]
|
||||||
pub fn begin_main_menu_bar(&self) -> Option<MainMenuBarToken<'ui>> {
|
pub fn begin_main_menu_bar(&self) -> Option<MainMenuBarToken<'_>> {
|
||||||
if unsafe { sys::igBeginMainMenuBar() } {
|
if unsafe { sys::igBeginMainMenuBar() } {
|
||||||
Some(MainMenuBarToken::new(self))
|
Some(MainMenuBarToken::new(self))
|
||||||
} else {
|
} else {
|
||||||
@ -167,7 +167,7 @@ impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
|
|||||||
///
|
///
|
||||||
/// Returns true if the menu item is activated.
|
/// Returns true if the menu item is activated.
|
||||||
#[doc(alias = "MenuItemBool")]
|
#[doc(alias = "MenuItemBool")]
|
||||||
pub fn build(self, ui: &Ui<'_>) -> bool {
|
pub fn build(self, ui: &Ui) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (label, shortcut) = ui.scratch_txt_with_opt(self.label, self.shortcut);
|
let (label, shortcut) = ui.scratch_txt_with_opt(self.label, self.shortcut);
|
||||||
sys::igMenuItem_Bool(label, shortcut, self.selected, self.enabled)
|
sys::igMenuItem_Bool(label, shortcut, self.selected, self.enabled)
|
||||||
@ -176,7 +176,7 @@ impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
|
|||||||
|
|
||||||
#[doc(alias = "MenuItemBool")]
|
#[doc(alias = "MenuItemBool")]
|
||||||
/// Builds the menu item using a mutable reference to selected state.
|
/// Builds the menu item using a mutable reference to selected state.
|
||||||
pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool {
|
pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool {
|
||||||
if self.selected(*selected).build(ui) {
|
if self.selected(*selected).build(ui) {
|
||||||
*selected = !*selected;
|
*selected = !*selected;
|
||||||
true
|
true
|
||||||
|
|||||||
@ -19,7 +19,7 @@ bitflags!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// # Widgets: Miscellaneous
|
/// # Widgets: Miscellaneous
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Renders a clickable button.
|
/// Renders a clickable button.
|
||||||
///
|
///
|
||||||
/// Returns true if this button was clicked.
|
/// Returns true if this button was clicked.
|
||||||
|
|||||||
@ -62,7 +62,7 @@ impl<T: AsRef<str>> ProgressBar<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the progress bar
|
/// Builds the progress bar
|
||||||
pub fn build(self, ui: &Ui<'_>) {
|
pub fn build(self, ui: &Ui) {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igProgressBar(
|
sys::igProgressBar(
|
||||||
self.fraction,
|
self.fraction,
|
||||||
|
|||||||
@ -108,7 +108,7 @@ impl<T: AsRef<str>> Selectable<T> {
|
|||||||
/// Builds the selectable.
|
/// Builds the selectable.
|
||||||
///
|
///
|
||||||
/// Returns true if the selectable was clicked.
|
/// Returns true if the selectable was clicked.
|
||||||
pub fn build(self, ui: &Ui<'_>) -> bool {
|
pub fn build(self, ui: &Ui) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igSelectable_Bool(
|
sys::igSelectable_Bool(
|
||||||
ui.scratch_txt(self.label),
|
ui.scratch_txt(self.label),
|
||||||
@ -120,7 +120,7 @@ impl<T: AsRef<str>> Selectable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the selectable using a mutable reference to selected state.
|
/// Builds the selectable using a mutable reference to selected state.
|
||||||
pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool {
|
pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool {
|
||||||
if self.selected(*selected).build(ui) {
|
if self.selected(*selected).build(ui) {
|
||||||
*selected = !*selected;
|
*selected = !*selected;
|
||||||
true
|
true
|
||||||
|
|||||||
@ -96,7 +96,7 @@ where
|
|||||||
/// Builds a slider that is bound to the given value.
|
/// Builds a slider that is bound to the given value.
|
||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool {
|
pub fn build(self, ui: &Ui, value: &mut Data) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ where
|
|||||||
/// Builds a horizontal array of multiple sliders attached to the given slice.
|
/// Builds a horizontal array of multiple sliders attached to the given slice.
|
||||||
///
|
///
|
||||||
/// Returns true if any slider value was changed.
|
/// Returns true if any slider value was changed.
|
||||||
pub fn build_array(self, ui: &Ui<'_>, values: &mut [Data]) -> bool {
|
pub fn build_array(self, ui: &Ui, values: &mut [Data]) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ where
|
|||||||
/// Builds a vertical slider that is bound to the given value.
|
/// Builds a vertical slider that is bound to the given value.
|
||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool {
|
pub fn build(self, ui: &Ui, value: &mut Data) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ where
|
|||||||
/// Builds an angle slider that is bound to the given value (in radians).
|
/// Builds an angle slider that is bound to the given value (in radians).
|
||||||
///
|
///
|
||||||
/// Returns true if the slider value was changed.
|
/// Returns true if the slider value was changed.
|
||||||
pub fn build(self, ui: &Ui<'_>, value_rad: &mut f32) -> bool {
|
pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
|
let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
|
||||||
|
|
||||||
|
|||||||
@ -87,7 +87,7 @@ impl<T: AsRef<str>> TabBar<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabBarToken<'ui>> {
|
pub fn begin(self, ui: &Ui) -> Option<TabBarToken<'_>> {
|
||||||
ui.tab_bar_with_flags(self.id, self.flags)
|
ui.tab_bar_with_flags(self.id, self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ impl<T: AsRef<str>> TabBar<T> {
|
|||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
///
|
///
|
||||||
/// Note: the closure is not called if no tabbar content is visible
|
/// Note: the closure is not called if no tabbar content is visible
|
||||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
|
||||||
self.begin(ui).map(|_tab| f())
|
self.begin(ui).map(|_tab| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ impl<'a, T: AsRef<str>> TabItem<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin<'ui>(self, ui: &'ui Ui<'_>) -> Option<TabItemToken<'ui>> {
|
pub fn begin(self, ui: &Ui) -> Option<TabItemToken<'_>> {
|
||||||
ui.tab_item_with_flags(self.label, self.opened, self.flags)
|
ui.tab_item_with_flags(self.label, self.opened, self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ impl<'a, T: AsRef<str>> TabItem<'a, T> {
|
|||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
///
|
///
|
||||||
/// Note: the closure is not called if the tab item is not selected
|
/// Note: the closure is not called if the tab item is not selected
|
||||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
|
||||||
self.begin(ui).map(|_tab| f())
|
self.begin(ui).map(|_tab| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ create_token!(
|
|||||||
drop { sys::igEndTabItem() }
|
drop { sys::igEndTabItem() }
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Ui<'_> {
|
impl Ui {
|
||||||
/// Creates a tab bar and returns a tab bar token, allowing you to append
|
/// Creates a tab bar and returns a tab bar token, allowing you to append
|
||||||
/// Tab items afterwards. This passes no flags. To pass flags explicitly,
|
/// Tab items afterwards. This passes no flags. To pass flags explicitly,
|
||||||
/// use [tab_bar_with_flags](Self::tab_bar_with_flags).
|
/// use [tab_bar_with_flags](Self::tab_bar_with_flags).
|
||||||
|
|||||||
@ -13,7 +13,7 @@ fn fmt_ptr() -> *const c_char {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Widgets: Text
|
/// # Widgets: Text
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Renders simple text
|
/// Renders simple text
|
||||||
#[doc(alias = "TextUnformatted")]
|
#[doc(alias = "TextUnformatted")]
|
||||||
pub fn text<T: AsRef<str>>(&self, text: T) {
|
pub fn text<T: AsRef<str>>(&self, text: T) {
|
||||||
|
|||||||
@ -241,7 +241,7 @@ impl<T: AsRef<str>, L: AsRef<str>> TreeNode<T, L> {
|
|||||||
/// rendered, the token can be popped by calling `.pop()`.
|
/// rendered, the token can be popped by calling `.pop()`.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the tree node is not open and no content should be rendered.
|
/// Returns `None` if the tree node is not open and no content should be rendered.
|
||||||
pub fn push<'ui>(self, ui: &Ui<'ui>) -> Option<TreeNodeToken<'ui>> {
|
pub fn push(self, ui: &Ui) -> Option<TreeNodeToken<'_>> {
|
||||||
let open = unsafe {
|
let open = unsafe {
|
||||||
if self.opened_cond != Condition::Never {
|
if self.opened_cond != Condition::Never {
|
||||||
sys::igSetNextItemOpen(self.opened, self.opened_cond as i32);
|
sys::igSetNextItemOpen(self.opened, self.opened_cond as i32);
|
||||||
@ -282,7 +282,7 @@ impl<T: AsRef<str>, L: AsRef<str>> TreeNode<T, L> {
|
|||||||
/// Returns the result of the closure, if it is called.
|
/// Returns the result of the closure, if it is called.
|
||||||
///
|
///
|
||||||
/// Note: the closure is not called if the tree node is not open.
|
/// Note: the closure is not called if the tree node is not open.
|
||||||
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui<'_>, f: F) -> Option<R> {
|
pub fn build<R, F: FnOnce() -> R>(self, ui: &Ui, f: F) -> Option<R> {
|
||||||
self.push(ui).map(|_node| f())
|
self.push(ui).map(|_node| f())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,11 +292,11 @@ impl<T: AsRef<str>, L: AsRef<str>> TreeNode<T, L> {
|
|||||||
/// If `TreeNodeFlags::NO_TREE_PUSH_ON_OPEN` was used when this token was created, calling `.pop()`
|
/// If `TreeNodeFlags::NO_TREE_PUSH_ON_OPEN` was used when this token was created, calling `.pop()`
|
||||||
/// is not mandatory and is a no-op.
|
/// is not mandatory and is a no-op.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct TreeNodeToken<'a>(core::marker::PhantomData<crate::Ui<'a>>, bool);
|
pub struct TreeNodeToken<'a>(core::marker::PhantomData<&'a crate::Ui>, bool);
|
||||||
|
|
||||||
impl<'a> TreeNodeToken<'a> {
|
impl<'a> TreeNodeToken<'a> {
|
||||||
/// Creates a new token type. This takes a bool for the no-op variant on NO_TREE_PUSH_ON_OPEN.
|
/// Creates a new token type. This takes a bool for the no-op variant on NO_TREE_PUSH_ON_OPEN.
|
||||||
pub(crate) fn new(_: &crate::Ui<'a>, execute_drop: bool) -> Self {
|
pub(crate) fn new(_: &crate::Ui, execute_drop: bool) -> Self {
|
||||||
Self(std::marker::PhantomData, execute_drop)
|
Self(std::marker::PhantomData, execute_drop)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
|||||||
///
|
///
|
||||||
/// This is the same as [build](Self::build) but is provided for consistent naming.
|
/// This is the same as [build](Self::build) but is provided for consistent naming.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin(self, ui: &Ui<'_>) -> bool {
|
pub fn begin(self, ui: &Ui) -> bool {
|
||||||
self.build(ui)
|
self.build(ui)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
|||||||
/// This is the same as [build_with_close_button](Self::build_with_close_button)
|
/// This is the same as [build_with_close_button](Self::build_with_close_button)
|
||||||
/// but is provided for consistent naming.
|
/// but is provided for consistent naming.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn begin_with_close_button(self, ui: &Ui<'_>, opened: &mut bool) -> bool {
|
pub fn begin_with_close_button(self, ui: &Ui, opened: &mut bool) -> bool {
|
||||||
self.build_with_close_button(ui, opened)
|
self.build_with_close_button(ui, opened)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
|||||||
/// Returns true if the collapsing header is open and content should be rendered.
|
/// Returns true if the collapsing header is open and content should be rendered.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build(self, ui: &Ui<'_>) -> bool {
|
pub fn build(self, ui: &Ui) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igCollapsingHeader_TreeNodeFlags(
|
sys::igCollapsingHeader_TreeNodeFlags(
|
||||||
ui.scratch_txt(self.label),
|
ui.scratch_txt(self.label),
|
||||||
@ -442,7 +442,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
|||||||
/// Returns true if the collapsing header is open and content should be rendered.
|
/// Returns true if the collapsing header is open and content should be rendered.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build_with_close_button(self, ui: &Ui<'_>, opened: &mut bool) -> bool {
|
pub fn build_with_close_button(self, ui: &Ui, opened: &mut bool) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::igCollapsingHeader_BoolPtr(
|
sys::igCollapsingHeader_BoolPtr(
|
||||||
ui.scratch_txt(self.label),
|
ui.scratch_txt(self.label),
|
||||||
@ -453,7 +453,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ui<'_> {
|
impl Ui {
|
||||||
/// Constructs a new collapsing header
|
/// Constructs a new collapsing header
|
||||||
#[doc(alias = "CollapsingHeader")]
|
#[doc(alias = "CollapsingHeader")]
|
||||||
pub fn collapsing_header(&self, label: impl AsRef<str>, flags: TreeNodeFlags) -> bool {
|
pub fn collapsing_header(&self, label: impl AsRef<str>, flags: TreeNodeFlags) -> bool {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use crate::Ui;
|
|||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct ChildWindow<'ui, Label> {
|
pub struct ChildWindow<'ui, Label> {
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
name: Label,
|
name: Label,
|
||||||
flags: WindowFlags,
|
flags: WindowFlags,
|
||||||
size: [f32; 2],
|
size: [f32; 2],
|
||||||
@ -22,7 +22,7 @@ pub struct ChildWindow<'ui, Label> {
|
|||||||
impl<'ui, Label: AsRef<str>> ChildWindow<'ui, Label> {
|
impl<'ui, Label: AsRef<str>> ChildWindow<'ui, Label> {
|
||||||
/// Creates a new child window builder with the given ID
|
/// Creates a new child window builder with the given ID
|
||||||
#[doc(alias = "BeginChildID")]
|
#[doc(alias = "BeginChildID")]
|
||||||
pub fn new(ui: &'ui Ui<'ui>, name: Label) -> ChildWindow<'ui, Label> {
|
pub fn new(ui: &'ui Ui, name: Label) -> ChildWindow<'ui, Label> {
|
||||||
ChildWindow {
|
ChildWindow {
|
||||||
ui,
|
ui,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::sys;
|
|||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
|
|
||||||
/// # Content region
|
/// # Content region
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns the current content boundaries (in *window coordinates*)
|
/// Returns the current content boundaries (in *window coordinates*)
|
||||||
#[doc(alias = "GetContentRegionMax")]
|
#[doc(alias = "GetContentRegionMax")]
|
||||||
pub fn content_region_max(&self) -> [f32; 2] {
|
pub fn content_region_max(&self) -> [f32; 2] {
|
||||||
|
|||||||
@ -111,7 +111,7 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// # Window utilities
|
/// # Window utilities
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns true if the current window appeared during this frame
|
/// Returns true if the current window appeared during this frame
|
||||||
#[doc(alias = "IsWindowAppearing")]
|
#[doc(alias = "IsWindowAppearing")]
|
||||||
pub fn is_window_appearing(&self) -> bool {
|
pub fn is_window_appearing(&self) -> bool {
|
||||||
@ -162,7 +162,7 @@ impl<'ui> Ui<'ui> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Window<'ui, 'a, Label> {
|
pub struct Window<'ui, 'a, Label> {
|
||||||
ui: &'ui Ui<'ui>,
|
ui: &'ui Ui,
|
||||||
name: Label,
|
name: Label,
|
||||||
opened: Option<&'a mut bool>,
|
opened: Option<&'a mut bool>,
|
||||||
flags: WindowFlags,
|
flags: WindowFlags,
|
||||||
@ -181,7 +181,7 @@ pub struct Window<'ui, 'a, Label> {
|
|||||||
|
|
||||||
impl<'ui, 'a, Label: AsRef<str>> Window<'ui, 'a, Label> {
|
impl<'ui, 'a, Label: AsRef<str>> Window<'ui, 'a, Label> {
|
||||||
/// Typically created via [`Ui::window`]
|
/// Typically created via [`Ui::window`]
|
||||||
pub fn new(ui: &'ui Ui<'ui>, name: Label) -> Self {
|
pub fn new(ui: &'ui Ui, name: Label) -> Self {
|
||||||
Window {
|
Window {
|
||||||
ui,
|
ui,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use crate::sys;
|
|||||||
use crate::Ui;
|
use crate::Ui;
|
||||||
|
|
||||||
/// # Window scrolling
|
/// # Window scrolling
|
||||||
impl<'ui> Ui<'ui> {
|
impl Ui {
|
||||||
/// Returns the horizontal scrolling position.
|
/// Returns the horizontal scrolling position.
|
||||||
///
|
///
|
||||||
/// Value is between 0.0 and self.scroll_max_x().
|
/// Value is between 0.0 and self.scroll_max_x().
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user