mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-10 21:18:36 +00:00
initial master branch impl
This commit is contained in:
parent
1fbe6331f4
commit
75d3f4b2fd
@ -4,6 +4,8 @@
|
||||
|
||||
- Fixed null pointers in zero-sized slices - [PR #779](https://github.com/imgui-rs/imgui-rs/pull/779)
|
||||
- Fixed `NewFrame` doc alias typo - [PR #791](https://github.com/imgui-rs/imgui-rs/pull/791)
|
||||
- Removed `GetWindowContentRegionMax`, `GetWindowContentRegionMin`, `GetContentRegionMax` --
|
||||
see https://github.com/ocornut/imgui/issues/7838 for more information.
|
||||
|
||||
## [0.12.0] - 2024-05-05
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fmt;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
use std::os::raw::c_char;
|
||||
use std::panic::catch_unwind;
|
||||
use std::process;
|
||||
use std::ptr;
|
||||
@ -62,8 +62,12 @@ impl fmt::Debug for ClipboardContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *const c_char {
|
||||
pub(crate) unsafe extern "C" fn get_clipboard_text(
|
||||
_user_data: *mut sys::ImGuiContext,
|
||||
) -> *const c_char {
|
||||
let result = catch_unwind(|| {
|
||||
let user_data = unsafe { (*sys::igGetPlatformIO()).Platform_ClipboardUserData };
|
||||
|
||||
let ctx = &mut *(user_data as *mut ClipboardContext);
|
||||
match ctx.backend.get() {
|
||||
Some(text) => {
|
||||
@ -79,8 +83,13 @@ pub(crate) unsafe extern "C" fn get_clipboard_text(user_data: *mut c_void) -> *c
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) unsafe extern "C" fn set_clipboard_text(user_data: *mut c_void, text: *const c_char) {
|
||||
pub(crate) unsafe extern "C" fn set_clipboard_text(
|
||||
_user_data: *mut sys::ImGuiContext,
|
||||
text: *const c_char,
|
||||
) {
|
||||
let result = catch_unwind(|| {
|
||||
let user_data = unsafe { (*sys::igGetPlatformIO()).Platform_ClipboardUserData };
|
||||
|
||||
let ctx = &mut *(user_data as *mut ClipboardContext);
|
||||
let text = CStr::from_ptr(text).to_owned();
|
||||
ctx.backend.set(text.to_str().unwrap());
|
||||
@ -97,15 +106,20 @@ impl Ui {
|
||||
/// Returns the current clipboard contents as text, or None if the clipboard is empty or cannot
|
||||
/// be accessed
|
||||
pub fn clipboard_text(&self) -> Option<String> {
|
||||
let io = self.io();
|
||||
io.get_clipboard_text_fn.and_then(|get_clipboard_text_fn| {
|
||||
let platform_io = unsafe { sys::igGetPlatformIO() };
|
||||
|
||||
let current_clipboard_text_fn = unsafe { (*platform_io).Platform_GetClipboardTextFn };
|
||||
|
||||
current_clipboard_text_fn.and_then(|get_clipboard_text_fn| {
|
||||
// Bypass FFI if we end up calling our own function anyway
|
||||
if get_clipboard_text_fn == get_clipboard_text {
|
||||
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
|
||||
let ctx = unsafe {
|
||||
&mut *((*platform_io).Platform_ClipboardUserData as *mut ClipboardContext)
|
||||
};
|
||||
ctx.backend.get()
|
||||
} else {
|
||||
unsafe {
|
||||
let text_ptr = get_clipboard_text_fn(io.clipboard_user_data);
|
||||
let text_ptr = get_clipboard_text_fn(sys::igGetCurrentContext());
|
||||
if text_ptr.is_null() || *text_ptr == b'\0' as c_char {
|
||||
None
|
||||
} else {
|
||||
@ -126,15 +140,19 @@ impl Ui {
|
||||
///
|
||||
/// Does nothing if the clipboard cannot be accessed.
|
||||
pub fn set_clipboard_text(&self, text: impl AsRef<str>) {
|
||||
let io = self.io();
|
||||
if let Some(set_clipboard_text_fn) = io.set_clipboard_text_fn {
|
||||
let platform_io = unsafe { sys::igGetPlatformIO() };
|
||||
let set_clipboard_text_fn = unsafe { (*platform_io).Platform_SetClipboardTextFn };
|
||||
|
||||
if let Some(set_clipboard_text_fn) = set_clipboard_text_fn {
|
||||
// Bypass FFI if we end up calling our own function anyway
|
||||
if set_clipboard_text_fn == set_clipboard_text {
|
||||
let ctx = unsafe { &mut *(io.clipboard_user_data as *mut ClipboardContext) };
|
||||
let ctx = unsafe {
|
||||
&mut *((*platform_io).Platform_ClipboardUserData as *mut ClipboardContext)
|
||||
};
|
||||
ctx.backend.set(text.as_ref());
|
||||
} else {
|
||||
unsafe {
|
||||
set_clipboard_text_fn(io.clipboard_user_data, self.scratch_txt(text));
|
||||
set_clipboard_text_fn(sys::igGetCurrentContext(), self.scratch_txt(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ impl Context {
|
||||
/// Sets the clipboard backend used for clipboard operations
|
||||
pub fn set_clipboard_backend<T: ClipboardBackend>(&mut self, backend: T) {
|
||||
let clipboard_ctx: Box<UnsafeCell<_>> = Box::new(ClipboardContext::new(backend).into());
|
||||
let io = self.io_mut();
|
||||
let io = self.platform_io_mut();
|
||||
io.set_clipboard_text_fn = Some(crate::clipboard::set_clipboard_text);
|
||||
io.get_clipboard_text_fn = Some(crate::clipboard::get_clipboard_text);
|
||||
|
||||
@ -451,8 +451,7 @@ fn test_ini_load_save() {
|
||||
let (_guard, mut ctx) = crate::test::test_ctx();
|
||||
let data = "[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0";
|
||||
Size=400,400";
|
||||
ctx.load_ini_settings(data);
|
||||
let mut buf = String::new();
|
||||
ctx.save_ini_settings(&mut buf);
|
||||
@ -502,6 +501,24 @@ impl Context {
|
||||
&mut *(sys::igGetIO() as *mut Io)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an immutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io(&self) -> &crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &self ensures we have shared ownership of PlatformIo.
|
||||
&*(sys::igGetPlatformIO() as *const crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
/// Returns a mutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io_mut(&mut self) -> &mut crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &mut self ensures exclusive ownership of PlatformIo.
|
||||
&mut *(sys::igGetPlatformIO() as *mut crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an immutable reference to the user interface style
|
||||
#[doc(alias = "GetStyle")]
|
||||
pub fn style(&self) -> &Style {
|
||||
@ -594,22 +611,6 @@ impl Context {
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
impl Context {
|
||||
/// Returns an immutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io(&self) -> &crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &self ensures we have shared ownership of PlatformIo.
|
||||
&*(sys::igGetPlatformIO() as *const crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
/// Returns a mutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io_mut(&mut self) -> &mut crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &mut self ensures exclusive ownership of PlatformIo.
|
||||
&mut *(sys::igGetPlatformIO() as *mut crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
/// Returns an immutable reference to the main [`Viewport`](crate::Viewport)
|
||||
pub fn main_viewport(&self) -> &crate::Viewport {
|
||||
unsafe {
|
||||
|
||||
396
imgui/src/docking_utils.rs
Normal file
396
imgui/src/docking_utils.rs
Normal file
@ -0,0 +1,396 @@
|
||||
use std::{
|
||||
ffi::{c_void, CStr},
|
||||
os::raw::{c_char, c_int},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
internal::{ImVector, RawCast},
|
||||
Io, ViewportFlags,
|
||||
};
|
||||
|
||||
todo!("needs to be checked with docking feature...");
|
||||
|
||||
/// Trait holding functions needed when the platform integration supports viewports.
|
||||
///
|
||||
/// Register it via [`Context::set_platform_backend()`](crate::context::Context::set_platform_backend())
|
||||
pub trait PlatformViewportBackend: 'static {
|
||||
/// Called by imgui when a new [`Viewport`] is created.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the creation of a platform window.
|
||||
/// The window should be invisible.
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui when a [`Viewport`] is about to be destroyed.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the destruction of the platform window.
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to make a [`Viewport`] visible.
|
||||
fn show_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to reposition a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `pos` specifies the position of the windows content area (excluding title bar etc.)
|
||||
fn set_window_pos(&mut self, viewport: &mut Viewport, pos: [f32; 2]);
|
||||
/// Called by imgui to get the position of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// You should return the position of the window's content area (excluding title bar etc.)
|
||||
fn get_window_pos(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to set the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `size` specifies the size of the window's content area (excluding title bar etc.)
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
/// Called by imgui to get the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// you should return the size of the window's content area (excluding title bar etc.)
|
||||
fn get_window_size(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to make a [`Viewport`] steal the focus.
|
||||
fn set_window_focus(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to query whether a [`Viewport`] is in focus.
|
||||
fn get_window_focus(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to query whether a [`Viewport`] is minimized.
|
||||
fn get_window_minimized(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to set a [`Viewport`] title.
|
||||
fn set_window_title(&mut self, viewport: &mut Viewport, title: &str);
|
||||
/// Called by imgui to set the opacity of an entire [`Viewport`].
|
||||
///
|
||||
/// If your backend does not support opactiy, it is safe to just do nothing in this function.
|
||||
fn set_window_alpha(&mut self, viewport: &mut Viewport, alpha: f32);
|
||||
fn update_window(&mut self, viewport: &mut Viewport);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
fn create_vk_surface(
|
||||
&mut self,
|
||||
viewport: &mut Viewport,
|
||||
instance: u64,
|
||||
out_surface: &mut u64,
|
||||
) -> i32;
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`PlatformViewportContext`].
|
||||
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_platform_user_data
|
||||
as *mut PlatformViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`RendererViewportContext`].
|
||||
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_renderer_user_data
|
||||
as *mut RendererViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.create_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.destroy_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_show_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.show_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_pos(viewport: *mut Viewport, pos: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_pos(
|
||||
viewport: *mut Viewport,
|
||||
out_pos: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let pos = ctx.backend.get_window_pos(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_pos = sys::ImVec2::new(pos[0], pos[1]);
|
||||
}
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_size(
|
||||
viewport: *mut Viewport,
|
||||
out_size: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let size = ctx.backend.get_window_size(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_size = sys::ImVec2::new(size[0], size[1]);
|
||||
}
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_focus(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_focus(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_focus(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_focus(unsafe { &mut *viewport })
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_minimized(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_minimized(unsafe { &mut *viewport })
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_title(viewport: *mut Viewport, title: *const c_char) {
|
||||
let ctx = get_platform_ctx();
|
||||
let title = unsafe { CStr::from_ptr(title).to_str().unwrap() };
|
||||
ctx.backend
|
||||
.set_window_title(unsafe { &mut *viewport }, title);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_alpha(viewport: *mut Viewport, alpha: f32) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_alpha(unsafe { &mut *viewport }, alpha);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_update_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.update_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.render_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.swap_buffers(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_create_vk_surface(
|
||||
viewport: *mut Viewport,
|
||||
instance: u64,
|
||||
_arg: *const c_void,
|
||||
out_surface: *mut u64,
|
||||
) -> c_int {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.create_vk_surface(unsafe { &mut *viewport }, instance, unsafe {
|
||||
&mut *out_surface
|
||||
})
|
||||
}
|
||||
|
||||
/// The default [`PlatformViewportBackend`], does nothing.
|
||||
pub(crate) struct DummyPlatformViewportBackend {}
|
||||
impl PlatformViewportBackend for DummyPlatformViewportBackend {
|
||||
fn create_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn show_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_pos(&mut self, _viewport: &mut Viewport, _pos: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_pos(&mut self, _viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, _viewport: &mut Viewport, _size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_size(&mut self, _viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_focus(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_focus(&mut self, _viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_minimized(&mut self, _viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_title(&mut self, _viewport: &mut Viewport, _title: &str) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_alpha(&mut self, _viewport: &mut Viewport, _alpha: f32) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn update_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_vk_surface(
|
||||
&mut self,
|
||||
_viewport: &mut Viewport,
|
||||
_instance: u64,
|
||||
_out_surface: &mut u64,
|
||||
) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`PlatformViewportBackend`].
|
||||
pub(crate) struct PlatformViewportContext {
|
||||
pub(crate) backend: Box<dyn PlatformViewportBackend>,
|
||||
}
|
||||
|
||||
impl PlatformViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyPlatformViewportBackend {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that holds optional functions for a rendering backend to support multiple viewports.
|
||||
///
|
||||
/// It is completely fine to not use this Backend at all, as all functions are optional.
|
||||
pub trait RendererViewportBackend: 'static {
|
||||
/// Called after [`PlatformViewportBackend::create_window()`].
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called before [`PlatformViewportBackend::destroy_window()`].
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called after [`PlatformViewportBackend::set_window_size()`].
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn renderer_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.create_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.destroy_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend
|
||||
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.render_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.swap_buffers(unsafe { &mut *viewport });
|
||||
}
|
||||
|
||||
/// The default [`RendererViewportBackend`], does nothing.
|
||||
pub(crate) struct DummyRendererViewportBackend {}
|
||||
impl RendererViewportBackend for DummyRendererViewportBackend {
|
||||
fn create_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, _viewport: &mut Viewport, _size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`RendererViewportBackend`].
|
||||
pub(crate) struct RendererViewportContext {
|
||||
pub(crate) backend: Box<dyn RendererViewportBackend>,
|
||||
}
|
||||
|
||||
impl RendererViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyRendererViewportBackend {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes a monitor that can be used by ImGui.
|
||||
#[repr(C)]
|
||||
pub struct PlatformMonitor {
|
||||
/// Position of the monitor on the virtual desktop.
|
||||
pub main_pos: [f32; 2],
|
||||
/// Size of the monitor on the virtual desktop.
|
||||
pub main_size: [f32; 2],
|
||||
/// Working position of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `main_pos` if not known.
|
||||
pub work_pos: [f32; 2],
|
||||
/// Working size of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `work_size` if not known.
|
||||
pub work_size: [f32; 2],
|
||||
pub dpi_scale: f32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_platform_monitor_memory_layout() {
|
||||
use std::mem;
|
||||
assert_eq!(
|
||||
mem::size_of::<PlatformMonitor>(),
|
||||
mem::size_of::<sys::ImGuiPlatformMonitor>()
|
||||
);
|
||||
assert_eq!(
|
||||
mem::align_of::<PlatformMonitor>(),
|
||||
mem::align_of::<sys::ImGuiPlatformMonitor>()
|
||||
);
|
||||
use sys::ImGuiPlatformMonitor;
|
||||
macro_rules! assert_field_offset {
|
||||
($l:ident, $r:ident) => {
|
||||
assert_eq!(
|
||||
memoffset::offset_of!(PlatformMonitor, $l),
|
||||
memoffset::offset_of!(ImGuiPlatformMonitor, $r)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(main_pos, MainPos);
|
||||
assert_field_offset!(main_size, MainSize);
|
||||
assert_field_offset!(work_pos, WorkPos);
|
||||
assert_field_offset!(work_size, WorkSize);
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowPos(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowSize(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
}
|
||||
@ -56,7 +56,7 @@ bitflags!(
|
||||
const SOURCE_EXTERN = sys::ImGuiDragDropFlags_SourceExtern;
|
||||
/// Automatically expire the payload if the source ceases to be submitted (otherwise
|
||||
/// payloads are persisting while being dragged)
|
||||
const SOURCE_AUTO_EXPIRE_PAYLOAD = sys::ImGuiDragDropFlags_SourceAutoExpirePayload;
|
||||
const SOURCE_AUTO_EXPIRE_PAYLOAD = sys::ImGuiDragDropFlags_PayloadAutoExpire;
|
||||
/// igAcceptDragDropPayload() will returns true even before the mouse button is released.
|
||||
/// You can then call igIsDelivery() to test if the payload needs to be delivered.
|
||||
const ACCEPT_BEFORE_DELIVERY = sys::ImGuiDragDropFlags_AcceptBeforeDelivery;
|
||||
|
||||
@ -318,6 +318,11 @@ pub struct FontConfig {
|
||||
pub font_builder_flags: u32,
|
||||
/// Brighten (>1.0) or darken (<1.0) font output
|
||||
pub rasterizer_multiply: f32,
|
||||
/// DPI scale for rasterization, not altering other font metrics:
|
||||
/// make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display.
|
||||
/// IMPORTANT: If you increase this it is expected that you increase font scale
|
||||
/// accordingly, otherwise quality may look lowered.
|
||||
pub rasterizer_density: f32,
|
||||
/// Explicitly specify the ellipsis character.
|
||||
///
|
||||
/// With multiple font sources the first specified ellipsis is used.
|
||||
@ -329,7 +334,7 @@ impl Default for FontConfig {
|
||||
fn default() -> FontConfig {
|
||||
FontConfig {
|
||||
size_pixels: 0.0,
|
||||
oversample_h: 3,
|
||||
oversample_h: 2,
|
||||
oversample_v: 1,
|
||||
pixel_snap_h: false,
|
||||
glyph_extra_spacing: [0.0, 0.0],
|
||||
@ -339,6 +344,7 @@ impl Default for FontConfig {
|
||||
glyph_max_advance_x: f32::MAX,
|
||||
font_builder_flags: 0,
|
||||
rasterizer_multiply: 1.0,
|
||||
rasterizer_density: 1.0,
|
||||
ellipsis_char: None,
|
||||
name: None,
|
||||
}
|
||||
@ -358,6 +364,7 @@ impl FontConfig {
|
||||
raw.GlyphMaxAdvanceX = self.glyph_max_advance_x;
|
||||
raw.FontBuilderFlags = self.font_builder_flags;
|
||||
raw.RasterizerMultiply = self.rasterizer_multiply;
|
||||
raw.RasterizerMultiply = self.rasterizer_density;
|
||||
// char is used as "unset" for EllipsisChar
|
||||
raw.EllipsisChar = self.ellipsis_char.map(|c| c as u32).unwrap_or(!0);
|
||||
if let Some(name) = self.name.as_ref() {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use std::ffi::c_short;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
use crate::fonts::atlas::{FontAtlas, FontId};
|
||||
@ -19,7 +20,9 @@ pub struct Font {
|
||||
pub config_data_count: i16,
|
||||
pub fallback_char: sys::ImWchar,
|
||||
pub ellipsis_char: sys::ImWchar,
|
||||
pub dot_char: sys::ImWchar,
|
||||
pub ellipsis_char_count: c_short,
|
||||
pub ellipsis_width: f32,
|
||||
pub ellipsis_char_step: f32,
|
||||
pub dirty_lookup_tables: bool,
|
||||
pub scale: f32,
|
||||
pub ascent: f32,
|
||||
@ -51,6 +54,7 @@ fn test_font_memory_layout() {
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(index_advance_x, IndexAdvanceX);
|
||||
assert_field_offset!(fallback_advance_x, FallbackAdvanceX);
|
||||
assert_field_offset!(font_size, FontSize);
|
||||
@ -62,7 +66,9 @@ fn test_font_memory_layout() {
|
||||
assert_field_offset!(config_data_count, ConfigDataCount);
|
||||
assert_field_offset!(fallback_char, FallbackChar);
|
||||
assert_field_offset!(ellipsis_char, EllipsisChar);
|
||||
assert_field_offset!(dot_char, DotChar);
|
||||
assert_field_offset!(ellipsis_char_count, EllipsisCharCount);
|
||||
assert_field_offset!(ellipsis_width, EllipsisWidth);
|
||||
assert_field_offset!(ellipsis_char_step, EllipsisCharStep);
|
||||
assert_field_offset!(dirty_lookup_tables, DirtyLookupTables);
|
||||
assert_field_offset!(scale, Scale);
|
||||
assert_field_offset!(ascent, Ascent);
|
||||
|
||||
@ -79,6 +79,18 @@ pub enum Key {
|
||||
F10 = sys::ImGuiKey_F10,
|
||||
F11 = sys::ImGuiKey_F11,
|
||||
F12 = sys::ImGuiKey_F12,
|
||||
F13 = sys::ImGuiKey_F13,
|
||||
F14 = sys::ImGuiKey_F14,
|
||||
F15 = sys::ImGuiKey_F15,
|
||||
F16 = sys::ImGuiKey_F16,
|
||||
F17 = sys::ImGuiKey_F17,
|
||||
F18 = sys::ImGuiKey_F18,
|
||||
F19 = sys::ImGuiKey_F19,
|
||||
F20 = sys::ImGuiKey_F20,
|
||||
F21 = sys::ImGuiKey_F21,
|
||||
F22 = sys::ImGuiKey_F22,
|
||||
F23 = sys::ImGuiKey_F23,
|
||||
F24 = sys::ImGuiKey_F24,
|
||||
Apostrophe = sys::ImGuiKey_Apostrophe,
|
||||
Comma = sys::ImGuiKey_Comma,
|
||||
Minus = sys::ImGuiKey_Minus,
|
||||
@ -112,6 +124,8 @@ pub enum Key {
|
||||
KeypadAdd = sys::ImGuiKey_KeypadAdd,
|
||||
KeypadEnter = sys::ImGuiKey_KeypadEnter,
|
||||
KeypadEqual = sys::ImGuiKey_KeypadEqual,
|
||||
AppBack = sys::ImGuiKey_AppBack,
|
||||
AppForward = sys::ImGuiKey_AppForward,
|
||||
GamepadStart = sys::ImGuiKey_GamepadStart,
|
||||
GamepadBack = sys::ImGuiKey_GamepadBack,
|
||||
GamepadFaceLeft = sys::ImGuiKey_GamepadFaceLeft,
|
||||
@ -147,11 +161,6 @@ pub enum Key {
|
||||
ReservedForModShift = sys::ImGuiKey_ReservedForModShift,
|
||||
ReservedForModAlt = sys::ImGuiKey_ReservedForModAlt,
|
||||
ReservedForModSuper = sys::ImGuiKey_ReservedForModSuper,
|
||||
ModCtrl = sys::ImGuiMod_Ctrl,
|
||||
ModShift = sys::ImGuiMod_Shift,
|
||||
ModAlt = sys::ImGuiMod_Alt,
|
||||
ModSuper = sys::ImGuiMod_Super,
|
||||
ModShortcut = sys::ImGuiMod_Shortcut,
|
||||
}
|
||||
|
||||
impl Key {
|
||||
@ -229,6 +238,18 @@ impl Key {
|
||||
Key::F10,
|
||||
Key::F11,
|
||||
Key::F12,
|
||||
Key::F13,
|
||||
Key::F14,
|
||||
Key::F15,
|
||||
Key::F16,
|
||||
Key::F17,
|
||||
Key::F18,
|
||||
Key::F19,
|
||||
Key::F20,
|
||||
Key::F21,
|
||||
Key::F22,
|
||||
Key::F23,
|
||||
Key::F24,
|
||||
Key::Apostrophe,
|
||||
Key::Comma,
|
||||
Key::Minus,
|
||||
@ -262,6 +283,8 @@ impl Key {
|
||||
Key::KeypadAdd,
|
||||
Key::KeypadEnter,
|
||||
Key::KeypadEqual,
|
||||
Key::AppBack,
|
||||
Key::AppForward,
|
||||
Key::GamepadStart,
|
||||
Key::GamepadBack,
|
||||
Key::GamepadFaceLeft,
|
||||
@ -328,34 +351,15 @@ impl FocusedWidget {
|
||||
|
||||
/// # Input: Keyboard
|
||||
impl Ui {
|
||||
/// Returns the key index of the given key identifier.
|
||||
///
|
||||
/// Equivalent to indexing the Io struct `key_map` field: `ui.io().key_map[key]`
|
||||
#[inline]
|
||||
#[doc(alias = "GetKeyIndex")]
|
||||
fn key_index(&self, key: Key) -> u32 {
|
||||
unsafe { sys::igGetKeyIndex(key as u32) }
|
||||
}
|
||||
/// Returns true if the key is being held.
|
||||
///
|
||||
/// Equivalent to indexing the Io struct `keys_down` field: `ui.io().keys_down[key_index]`
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyDown")]
|
||||
pub fn is_key_down(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
self.is_key_index_down(key_index)
|
||||
}
|
||||
|
||||
/// Same as [`is_key_down`](Self::is_key_down) but takes a key index. The meaning of
|
||||
/// index is defined by your backend implementation.
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyDown")]
|
||||
pub fn is_key_index_down(&self, key_index: u32) -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "docking")] {
|
||||
unsafe { sys::igIsKeyDown_Nil(key_index) }
|
||||
unsafe { sys::igIsKeyDown_Nil(key as u32) }
|
||||
} else {
|
||||
unsafe { sys::igIsKeyDown(key_index) }
|
||||
unsafe { sys::igIsKeyDown(key as u32) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -366,22 +370,11 @@ impl Ui {
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyPressed")]
|
||||
pub fn is_key_pressed(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
self.is_key_index_pressed(key_index)
|
||||
}
|
||||
|
||||
/// Same as [`is_key_pressed`](Self::is_key_pressed) but takes a key index.
|
||||
///
|
||||
/// The meaning of index is defined by your backend
|
||||
/// implementation.
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyPressed")]
|
||||
pub fn is_key_index_pressed(&self, key_index: u32) -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "docking")] {
|
||||
unsafe { sys::igIsKeyPressed_Bool(key_index, true) }
|
||||
unsafe { sys::igIsKeyPressed_Bool(key as u32, true) }
|
||||
} else {
|
||||
unsafe { sys::igIsKeyPressed(key_index, true) }
|
||||
unsafe { sys::igIsKeyPressed(key as u32, true) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -392,23 +385,11 @@ impl Ui {
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyPressed")]
|
||||
pub fn is_key_pressed_no_repeat(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
self.is_key_index_pressed_no_repeat(key_index)
|
||||
}
|
||||
|
||||
/// Same as [`is_key_pressed_no_repeat`](Self::is_key_pressed_no_repeat)
|
||||
/// but takes a key index.
|
||||
///
|
||||
/// The meaning of index is defined by your backend
|
||||
/// implementation.
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyPressed")]
|
||||
pub fn is_key_index_pressed_no_repeat(&self, key_index: u32) -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "docking")] {
|
||||
unsafe { sys::igIsKeyPressed_Bool(key_index, false) }
|
||||
unsafe { sys::igIsKeyPressed_Bool(key as u32, false) }
|
||||
} else {
|
||||
unsafe { sys::igIsKeyPressed(key_index, false) }
|
||||
unsafe { sys::igIsKeyPressed(key as u32, false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -417,22 +398,11 @@ impl Ui {
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyReleased")]
|
||||
pub fn is_key_released(&self, key: Key) -> bool {
|
||||
let key_index = self.key_index(key);
|
||||
self.is_key_index_released(key_index)
|
||||
}
|
||||
|
||||
/// Same as [`is_key_released`](Self::is_key_released) but takes a key index.
|
||||
///
|
||||
/// The meaning of index is defined by your backend
|
||||
/// implementation.
|
||||
#[inline]
|
||||
#[doc(alias = "IsKeyReleased")]
|
||||
pub fn is_key_index_released(&self, key_index: u32) -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "docking")] {
|
||||
unsafe { sys::igIsKeyReleased_Nil(key_index) }
|
||||
unsafe { sys::igIsKeyReleased_Nil(key as u32) }
|
||||
} else {
|
||||
unsafe { sys::igIsKeyReleased(key_index) }
|
||||
unsafe { sys::igIsKeyReleased(key as u32) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,15 +414,7 @@ impl Ui {
|
||||
#[inline]
|
||||
#[doc(alias = "GetKeyPressedAmount")]
|
||||
pub fn key_pressed_amount(&self, key: Key, repeat_delay: f32, rate: f32) -> u32 {
|
||||
let key_index = self.key_index(key);
|
||||
self.key_index_pressed_amount(key_index, repeat_delay, rate)
|
||||
}
|
||||
|
||||
/// Same as [`crate::Ui::key_pressed_amount`] but takes a key index.
|
||||
#[inline]
|
||||
#[doc(alias = "GetKeyPressedAmount")]
|
||||
pub fn key_index_pressed_amount(&self, key_index: u32, repeat_delay: f32, rate: f32) -> u32 {
|
||||
unsafe { sys::igGetKeyPressedAmount(key_index, repeat_delay, rate) as u32 }
|
||||
unsafe { sys::igGetKeyPressedAmount(key as u32, repeat_delay, rate) as u32 }
|
||||
}
|
||||
|
||||
/// Focuses keyboard on the next widget.
|
||||
|
||||
@ -81,6 +81,34 @@ impl MouseCursor {
|
||||
pub const COUNT: usize = sys::ImGuiMouseCursor_COUNT as usize;
|
||||
}
|
||||
|
||||
// pub const ImGuiMouseSource_Mouse: ImGuiMouseSource = 0;
|
||||
// pub const ImGuiMouseSource_TouchScreen: ImGuiMouseSource = 1;
|
||||
// pub const ImGuiMouseSource_Pen: ImGuiMouseSource = 2;
|
||||
// pub const ImGuiMouseSource_COUNT: ImGuiMouseSource = 3;
|
||||
|
||||
/// Notates the type and origin of a mouse input.
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum MouseSource {
|
||||
/// From an normal cursor mouse.
|
||||
Mouse = sys::ImGuiMouseSource_Mouse,
|
||||
/// From a touchscreen used with a finger.
|
||||
Touchscreen = sys::ImGuiMouseSource_TouchScreen,
|
||||
/// From a pen.
|
||||
Pen = sys::ImGuiMouseSource_Pen,
|
||||
}
|
||||
|
||||
impl MouseSource {
|
||||
/// All possible [`MouseSource`] varirants
|
||||
pub const VARIANTS: [MouseSource; MouseSource::COUNT] = [
|
||||
MouseSource::Mouse,
|
||||
MouseSource::Touchscreen,
|
||||
MouseSource::Pen,
|
||||
];
|
||||
/// Total count of [`MouseSource`] variants
|
||||
pub const COUNT: usize = sys::ImGuiMouseSource_COUNT as usize;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mouse_cursor_variants() {
|
||||
for (idx, &value) in MouseCursor::VARIANTS.iter().enumerate() {
|
||||
@ -122,7 +150,13 @@ impl Ui {
|
||||
/// Returns true if the given mouse button was double-clicked
|
||||
#[doc(alias = "IsMouseDoubleClicked")]
|
||||
pub fn is_mouse_double_clicked(&self, button: MouseButton) -> bool {
|
||||
unsafe { sys::igIsMouseDoubleClicked(button as i32) }
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "docking")] {
|
||||
unsafe { sys::igIsMouseDoubleClicked_Nil(button as i32) }
|
||||
} else {
|
||||
unsafe { sys::igIsMouseDoubleClicked(button as i32) }
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Returns true if the given mouse button was released (went from down to !down)
|
||||
#[doc(alias = "IsMouseReleased")]
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
//! Internal raw utilities (don't use unless you know what you're doing!)
|
||||
|
||||
use std::slice;
|
||||
use std::{ffi::c_int, slice};
|
||||
|
||||
/// A generic version of the raw imgui-sys ImVector struct types
|
||||
#[repr(C)]
|
||||
pub struct ImVector<T> {
|
||||
size: i32,
|
||||
capacity: i32,
|
||||
size: c_int,
|
||||
capacity: c_int,
|
||||
pub(crate) data: *mut T,
|
||||
}
|
||||
|
||||
|
||||
255
imgui/src/io.rs
255
imgui/src/io.rs
@ -9,7 +9,7 @@ use crate::fonts::font::Font;
|
||||
use crate::input::keyboard::Key;
|
||||
use crate::input::mouse::MouseButton;
|
||||
use crate::internal::{ImVector, RawCast};
|
||||
use crate::sys;
|
||||
use crate::{sys, MouseSource};
|
||||
|
||||
bitflags! {
|
||||
/// Configuration flags
|
||||
@ -61,22 +61,31 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct ViewportFlags: u32 {
|
||||
const IS_PLATFORM_WINDOW = sys::ImGuiViewportFlags_IsPlatformWindow;
|
||||
const IS_PLATFORM_MONITOR = sys::ImGuiViewportFlags_IsPlatformMonitor;
|
||||
const OWNED_BY_APP = sys::ImGuiViewportFlags_OwnedByApp;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_DECORATION = sys::ImGuiViewportFlags_NoDecoration;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_TASK_BAR_ICON = sys::ImGuiViewportFlags_NoTaskBarIcon;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_FOCUS_ON_APPEARING = sys::ImGuiViewportFlags_NoFocusOnAppearing;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_FOCUS_ON_CLICK = sys::ImGuiViewportFlags_NoFocusOnClick;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_INPUTS = sys::ImGuiViewportFlags_NoInputs;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_RENDERER_CLEAR = sys::ImGuiViewportFlags_NoRendererClear;
|
||||
#[cfg(feature = "docking")]
|
||||
const TOP_MOST = sys::ImGuiViewportFlags_TopMost;
|
||||
#[cfg(feature = "docking")]
|
||||
const MINIMIZED = sys::ImGuiViewportFlags_Minimized;
|
||||
#[cfg(feature = "docking")]
|
||||
const NO_AUTO_MERGE = sys::ImGuiViewportFlags_NoAutoMerge;
|
||||
#[cfg(feature = "docking")]
|
||||
const CAN_HOST_OTHER_WINDOWS = sys::ImGuiViewportFlags_CanHostOtherWindows;
|
||||
}
|
||||
}
|
||||
@ -107,61 +116,6 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
/// An input identifier for navigation
|
||||
#[repr(u32)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum NavInput {
|
||||
Activate = sys::ImGuiNavInput_Activate,
|
||||
Cancel = sys::ImGuiNavInput_Cancel,
|
||||
Input = sys::ImGuiNavInput_Input,
|
||||
Menu = sys::ImGuiNavInput_Menu,
|
||||
DpadLeft = sys::ImGuiNavInput_DpadLeft,
|
||||
DpadRight = sys::ImGuiNavInput_DpadRight,
|
||||
DpadUp = sys::ImGuiNavInput_DpadUp,
|
||||
DpadDown = sys::ImGuiNavInput_DpadDown,
|
||||
LStickLeft = sys::ImGuiNavInput_LStickLeft,
|
||||
LStickRight = sys::ImGuiNavInput_LStickRight,
|
||||
LStickUp = sys::ImGuiNavInput_LStickUp,
|
||||
LStickDown = sys::ImGuiNavInput_LStickDown,
|
||||
FocusPrev = sys::ImGuiNavInput_FocusPrev,
|
||||
FocusNext = sys::ImGuiNavInput_FocusNext,
|
||||
TweakSlow = sys::ImGuiNavInput_TweakSlow,
|
||||
TweakFast = sys::ImGuiNavInput_TweakFast,
|
||||
}
|
||||
|
||||
impl NavInput {
|
||||
/// All possible `NavInput` variants
|
||||
pub const VARIANTS: [NavInput; NavInput::COUNT] = [
|
||||
NavInput::Activate,
|
||||
NavInput::Cancel,
|
||||
NavInput::Input,
|
||||
NavInput::Menu,
|
||||
NavInput::DpadLeft,
|
||||
NavInput::DpadRight,
|
||||
NavInput::DpadUp,
|
||||
NavInput::DpadDown,
|
||||
NavInput::LStickLeft,
|
||||
NavInput::LStickRight,
|
||||
NavInput::LStickUp,
|
||||
NavInput::LStickDown,
|
||||
NavInput::FocusPrev,
|
||||
NavInput::FocusNext,
|
||||
NavInput::TweakSlow,
|
||||
NavInput::TweakFast,
|
||||
];
|
||||
/// Amount of internal/hidden variants (not exposed by imgui-rs)
|
||||
const INTERNAL_COUNT: usize = 0;
|
||||
/// Total count of `NavInput` variants
|
||||
pub const COUNT: usize = sys::ImGuiNavInput_COUNT as usize - NavInput::INTERNAL_COUNT;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nav_input_variants() {
|
||||
for (idx, &value) in NavInput::VARIANTS.iter().enumerate() {
|
||||
assert_eq!(idx, value as usize);
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings and inputs/outputs for imgui-rs
|
||||
#[repr(C)]
|
||||
pub struct Io {
|
||||
@ -178,24 +132,8 @@ pub struct Io {
|
||||
|
||||
pub(crate) ini_filename: *const c_char,
|
||||
pub(crate) log_filename: *const c_char,
|
||||
|
||||
/// Time for a double-click, in seconds
|
||||
pub mouse_double_click_time: f32,
|
||||
/// Distance threshold to stay in to validate a double-click, in pixels
|
||||
pub mouse_double_click_max_dist: f32,
|
||||
/// Distance threshold before considering we are dragging
|
||||
pub mouse_drag_threshold: f32,
|
||||
/// When holding a key/button, time before it starts repeating, in seconds
|
||||
pub key_repeat_delay: f32,
|
||||
/// When holding a key/button, rate at which it repeats, in seconds
|
||||
pub key_repeat_rate: f32,
|
||||
|
||||
/// Delay on hover before [`ui.is_item_hovered_with_flags(ItemHoveredFlags::DELAY_NORMAL)`](crate::Ui::is_item_hovered_with_flags) returns true
|
||||
pub hover_delay_normal: f32,
|
||||
/// Delay on hover before [`ui.is_item_hovered_with_flags(ItemHoveredFlags::DELAY_SHORT)`](crate::Ui::is_item_hovered_with_flags) returns true
|
||||
pub hover_delay_short: f32,
|
||||
|
||||
user_data: *mut c_void,
|
||||
|
||||
pub(crate) fonts: *mut FontAtlas,
|
||||
|
||||
/// Global scale for all fonts
|
||||
@ -204,28 +142,10 @@ pub struct Io {
|
||||
pub font_allow_user_scaling: bool,
|
||||
|
||||
pub(crate) font_default: *mut Font,
|
||||
|
||||
/// For retina display or other situations where window coordinates are different from
|
||||
/// framebuffer coordinates
|
||||
pub display_framebuffer_scale: [f32; 2],
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_no_split: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_with_shift: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_always_tab_bar: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_transparent_payload: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_auto_merge: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_task_bar_icon: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_decoration: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_default_parent: bool,
|
||||
|
||||
/// Request imgui-rs to draw a mouse cursor for you
|
||||
pub mouse_draw_cursor: bool,
|
||||
/// macOS-style input behavior.
|
||||
@ -238,6 +158,11 @@ pub struct Io {
|
||||
/// * Double-click selects by word instead of selecting the whole text
|
||||
/// * Multi-selection in lists uses Cmd/Super instead of Ctrl
|
||||
pub config_mac_os_behaviors: bool,
|
||||
|
||||
/// Swap Activate/Cancel (A<>B) buttons, to match the typical "Nintendo/Japanese consoles"
|
||||
/// button layout when using Gamepad navigation
|
||||
pub config_nav_swap_gamepad_buttons: bool,
|
||||
|
||||
/// Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up)
|
||||
/// will be spread over multiple frames, improving interactions with low framerates.
|
||||
pub config_input_trickle_event_queue: bool,
|
||||
@ -262,23 +187,44 @@ pub struct Io {
|
||||
/// Set to -1.0 to disable.
|
||||
pub config_memory_compact_timer: f32,
|
||||
|
||||
/// Time for a double-click, in seconds
|
||||
pub mouse_double_click_time: f32,
|
||||
/// Distance threshold to stay in to validate a double-click, in pixels
|
||||
pub mouse_double_click_max_dist: f32,
|
||||
/// Distance threshold before considering we are dragging
|
||||
pub mouse_drag_threshold: f32,
|
||||
/// When holding a key/button, time before it starts repeating, in seconds
|
||||
pub key_repeat_delay: f32,
|
||||
/// When holding a key/button, rate at which it repeats, in seconds
|
||||
pub key_repeat_rate: f32,
|
||||
|
||||
/// Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro.
|
||||
/// - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability.
|
||||
/// - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.
|
||||
pub config_debug_is_debugger_present: bool,
|
||||
|
||||
/// Highlight and show an error message when multiple items have conflicting identifiers.
|
||||
pub config_debug_highlight_id_conflicts: bool,
|
||||
|
||||
/// First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows.
|
||||
pub config_debug_begin_return_value_once: bool,
|
||||
|
||||
/// Some calls to Begin()/BeginChild() will return false.
|
||||
/// Will cycle through window depths then repeat.
|
||||
pub config_debug_begin_return_value_loop: bool,
|
||||
|
||||
/// Ignore `add_focus_event(false)`, consequently not calling io.clear_input_keys()/io.clear_mouse_input() in input processing.
|
||||
pub config_debug_ignore_focus_loss: bool,
|
||||
|
||||
/// Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
|
||||
pub config_debug_ini_settings: bool,
|
||||
|
||||
pub(crate) backend_platform_name: *const c_char,
|
||||
pub(crate) backend_renderer_name: *const c_char,
|
||||
pub(crate) backend_platform_user_data: *mut c_void,
|
||||
pub(crate) backend_renderer_user_data: *mut c_void,
|
||||
backend_language_user_data: *mut c_void,
|
||||
pub(crate) get_clipboard_text_fn:
|
||||
Option<unsafe extern "C" fn(user_data: *mut c_void) -> *const c_char>,
|
||||
pub(crate) set_clipboard_text_fn:
|
||||
Option<unsafe extern "C" fn(user_data: *mut c_void, text: *const c_char)>,
|
||||
pub(crate) clipboard_user_data: *mut c_void,
|
||||
pub set_platform_ime_data_fn: Option<
|
||||
unsafe extern "C" fn(
|
||||
viewport: *mut sys::ImGuiViewport,
|
||||
data: *mut sys::ImGuiPlatformImeData,
|
||||
),
|
||||
>,
|
||||
unused_padding: *mut c_void,
|
||||
|
||||
/// When true, imgui-rs will use the mouse inputs, so do not dispatch them to your main
|
||||
/// game/application
|
||||
pub want_capture_mouse: bool,
|
||||
@ -315,23 +261,13 @@ pub struct Io {
|
||||
pub metrics_render_windows: i32,
|
||||
/// Number of active windows
|
||||
pub metrics_active_windows: i32,
|
||||
/// Number of active internal imgui-rs allocations
|
||||
pub metrics_active_allocations: i32,
|
||||
|
||||
/// Mouse delta.
|
||||
///
|
||||
/// Note that this is zero if either current or previous position is invalid ([f32::MAX,
|
||||
/// f32::MAX]), so a disappearing/reappearing mouse won't have a huge delta.
|
||||
pub mouse_delta: [f32; 2],
|
||||
/// Map of indices into the `keys_down` entries array, which represent your "native" keyboard
|
||||
/// state
|
||||
pub key_map: [u32; sys::ImGuiKey_COUNT as usize],
|
||||
/// Keyboard keys that are pressed (indexing defined by the user/application)
|
||||
pub keys_down: [bool; sys::ImGuiKey_COUNT as usize],
|
||||
/// Gamepad inputs.
|
||||
///
|
||||
/// Cleared back to zero after each frame. Keyboard keys will be auto-mapped and written
|
||||
/// here by `frame()`.
|
||||
pub nav_inputs: [f32; NavInput::COUNT + NavInput::INTERNAL_COUNT],
|
||||
pub(crate) ctx: *mut sys::ImGuiContext,
|
||||
/// Mouse position, in pixels.
|
||||
///
|
||||
/// Set to [f32::MAX, f32::MAX] if mouse is unavailable (on another screen, etc.).
|
||||
@ -347,8 +283,10 @@ pub struct Io {
|
||||
/// Most users don't have a mouse with a horizontal wheel, and may not be filled by all
|
||||
/// backends.
|
||||
pub mouse_wheel_h: f32,
|
||||
#[cfg(feature = "docking")]
|
||||
mouse_hovered_viewport: sys::ImGuiID,
|
||||
|
||||
/// Notates the origin of the mouse input event.
|
||||
pub mouse_source: MouseSource,
|
||||
|
||||
/// Keyboard modifier pressed: Control
|
||||
pub key_ctrl: bool,
|
||||
/// Keyboard modifier pressed: Shift
|
||||
@ -358,7 +296,11 @@ pub struct Io {
|
||||
/// Keyboard modifier pressed: Cmd/Super/Windows
|
||||
pub key_super: bool,
|
||||
key_mods: sys::ImGuiKeyChord,
|
||||
keys_data: [sys::ImGuiKeyData; sys::ImGuiKey_COUNT as usize],
|
||||
|
||||
// note: this *should* be `ImGuiKey_COUNT` but that appears to end up
|
||||
// being a very different value -- I suspect there's some namespace collision
|
||||
// going on here.
|
||||
keys_data: [sys::ImGuiKeyData; sys::ImGuiKey_NamedKey_COUNT as usize],
|
||||
|
||||
pub want_capture_mouse_unless_popup_close: bool,
|
||||
|
||||
@ -372,6 +314,10 @@ pub struct Io {
|
||||
mouse_released: [bool; 5],
|
||||
mouse_down_owned: [bool; 5],
|
||||
mouse_down_owned_unless_popup_close: [bool; 5],
|
||||
|
||||
mouse_wheel_request_axis_swap: bool,
|
||||
mouse_ctrl_left_as_right_click: bool,
|
||||
|
||||
mouse_down_duration: [f32; 5],
|
||||
mouse_down_duration_prev: [f32; 5],
|
||||
#[cfg(feature = "docking")]
|
||||
@ -390,6 +336,38 @@ pub struct Io {
|
||||
|
||||
input_queue_surrogate: sys::ImWchar16,
|
||||
input_queue_characters: ImVector<sys::ImWchar>,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
mouse_hovered_viewport: sys::ImGuiID,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_no_split: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_with_shift: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_always_tab_bar: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_docking_transparent_payload: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_auto_merge: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_task_bar_icon: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_decoration: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub config_viewports_no_default_parent: bool,
|
||||
// pub(crate) get_clipboard_text_fn:
|
||||
// Option<unsafe extern "C" fn(user_data: *mut c_void) -> *const c_char>,
|
||||
// pub(crate) set_clipboard_text_fn:
|
||||
// Option<unsafe extern "C" fn(user_data: *mut c_void, text: *const c_char)>,
|
||||
// pub(crate) clipboard_user_data: *mut c_void,
|
||||
// pub set_platform_ime_data_fn: Option<
|
||||
// unsafe extern "C" fn(
|
||||
// viewport: *mut sys::ImGuiViewport,
|
||||
// data: *mut sys::ImGuiPlatformImeData,
|
||||
// ),
|
||||
// >,
|
||||
// unused_padding: *mut c_void,
|
||||
}
|
||||
|
||||
unsafe impl RawCast<sys::ImGuiIO> for Io {}
|
||||
@ -408,7 +386,7 @@ impl Io {
|
||||
#[doc(alias = "ClearCharacters")]
|
||||
pub fn clear_input_characters(&mut self) {
|
||||
unsafe {
|
||||
sys::ImGuiIO_ClearInputCharacters(self.raw_mut());
|
||||
sys::ImGuiIO_ClearInputKeys(self.raw_mut());
|
||||
}
|
||||
}
|
||||
/// Peek character input buffer, return a copy of entire buffer
|
||||
@ -467,32 +445,6 @@ impl Io {
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Key> for Io {
|
||||
type Output = u32;
|
||||
fn index(&self, index: Key) -> &u32 {
|
||||
&self.key_map[index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<Key> for Io {
|
||||
fn index_mut(&mut self, index: Key) -> &mut u32 {
|
||||
&mut self.key_map[index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<NavInput> for Io {
|
||||
type Output = f32;
|
||||
fn index(&self, index: NavInput) -> &f32 {
|
||||
&self.nav_inputs[index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<NavInput> for Io {
|
||||
fn index_mut(&mut self, index: NavInput) -> &mut f32 {
|
||||
&mut self.nav_inputs[index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<MouseButton> for Io {
|
||||
type Output = bool;
|
||||
fn index(&self, index: MouseButton) -> &bool {
|
||||
@ -540,8 +492,6 @@ fn test_io_memory_layout() {
|
||||
assert_field_offset!(mouse_drag_threshold, MouseDragThreshold);
|
||||
assert_field_offset!(key_repeat_delay, KeyRepeatDelay);
|
||||
assert_field_offset!(key_repeat_rate, KeyRepeatRate);
|
||||
assert_field_offset!(hover_delay_normal, HoverDelayNormal);
|
||||
assert_field_offset!(hover_delay_short, HoverDelayShort);
|
||||
assert_field_offset!(user_data, UserData);
|
||||
assert_field_offset!(fonts, Fonts);
|
||||
assert_field_offset!(font_global_scale, FontGlobalScale);
|
||||
@ -572,11 +522,6 @@ fn test_io_memory_layout() {
|
||||
assert_field_offset!(backend_platform_user_data, BackendPlatformUserData);
|
||||
assert_field_offset!(backend_renderer_user_data, BackendRendererUserData);
|
||||
assert_field_offset!(backend_language_user_data, BackendLanguageUserData);
|
||||
assert_field_offset!(get_clipboard_text_fn, GetClipboardTextFn);
|
||||
assert_field_offset!(set_clipboard_text_fn, SetClipboardTextFn);
|
||||
assert_field_offset!(clipboard_user_data, ClipboardUserData);
|
||||
assert_field_offset!(set_platform_ime_data_fn, SetPlatformImeDataFn);
|
||||
assert_field_offset!(unused_padding, _UnusedPadding);
|
||||
assert_field_offset!(want_capture_mouse, WantCaptureMouse);
|
||||
assert_field_offset!(want_capture_keyboard, WantCaptureKeyboard);
|
||||
assert_field_offset!(want_text_input, WantTextInput);
|
||||
@ -589,11 +534,7 @@ fn test_io_memory_layout() {
|
||||
assert_field_offset!(metrics_render_indices, MetricsRenderIndices);
|
||||
assert_field_offset!(metrics_render_windows, MetricsRenderWindows);
|
||||
assert_field_offset!(metrics_active_windows, MetricsActiveWindows);
|
||||
assert_field_offset!(metrics_active_allocations, MetricsActiveAllocations);
|
||||
assert_field_offset!(mouse_delta, MouseDelta);
|
||||
assert_field_offset!(key_map, KeyMap);
|
||||
assert_field_offset!(keys_down, KeysDown);
|
||||
assert_field_offset!(nav_inputs, NavInputs);
|
||||
assert_field_offset!(mouse_pos, MousePos);
|
||||
assert_field_offset!(mouse_down, MouseDown);
|
||||
assert_field_offset!(mouse_wheel, MouseWheel);
|
||||
|
||||
@ -21,6 +21,12 @@ impl Ui {
|
||||
unsafe { sys::igSeparator() }
|
||||
}
|
||||
|
||||
/// Renders a separator with text.
|
||||
#[doc(alias = "SeparatorText")]
|
||||
pub fn separator_with_text(&self, text: impl AsRef<str>) {
|
||||
unsafe { sys::igSeparatorText(self.scratch_txt(text)) }
|
||||
}
|
||||
|
||||
/// Call between widgets or groups to layout them horizontally.
|
||||
///
|
||||
/// X position is given in window coordinates.
|
||||
|
||||
@ -105,7 +105,6 @@ pub use self::input_widget::*;
|
||||
pub use self::io::*;
|
||||
pub use self::layout::*;
|
||||
pub use self::list_clipper::ListClipper;
|
||||
#[cfg(feature = "docking")]
|
||||
pub use self::platform_io::*;
|
||||
pub use self::plothistogram::PlotHistogram;
|
||||
pub use self::plotlines::PlotLines;
|
||||
@ -149,6 +148,8 @@ mod columns;
|
||||
mod context;
|
||||
#[cfg(feature = "docking")]
|
||||
mod dock_space;
|
||||
#[cfg(feature = "docking")]
|
||||
mod docking_utils;
|
||||
pub mod drag_drop;
|
||||
pub mod draw_list;
|
||||
mod fonts;
|
||||
@ -159,8 +160,8 @@ mod io;
|
||||
mod layout;
|
||||
mod list_clipper;
|
||||
mod math;
|
||||
#[cfg(feature = "docking")]
|
||||
mod platform_io;
|
||||
|
||||
mod plothistogram;
|
||||
mod plotlines;
|
||||
mod popups;
|
||||
@ -683,17 +684,21 @@ impl Ui {
|
||||
/// ```
|
||||
#[doc(alias = "BeginTooltip", alias = "EndTootip")]
|
||||
pub fn tooltip<F: FnOnce()>(&self, f: F) {
|
||||
unsafe { sys::igBeginTooltip() };
|
||||
f();
|
||||
unsafe { sys::igEndTooltip() };
|
||||
if unsafe { sys::igBeginTooltip() } {
|
||||
f();
|
||||
unsafe { sys::igEndTooltip() };
|
||||
}
|
||||
}
|
||||
/// Construct a tooltip window that can have any kind of content.
|
||||
///
|
||||
/// Returns a `TooltipToken` that must be ended by calling `.end()`
|
||||
/// Can return a `TooltipToken` that must be ended by calling `.end()`
|
||||
#[doc(alias = "BeginTooltip")]
|
||||
pub fn begin_tooltip(&self) -> TooltipToken<'_> {
|
||||
unsafe { sys::igBeginTooltip() };
|
||||
TooltipToken::new(self)
|
||||
pub fn begin_tooltip(&self) -> Option<TooltipToken<'_>> {
|
||||
if unsafe { sys::igBeginTooltip() } {
|
||||
Some(TooltipToken::new(self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Shortcut to call [`Self::tooltip`] with simple text content.
|
||||
@ -709,7 +714,7 @@ impl Ui {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[doc(alias = "BeginTooltip", alias = "EndTootip")]
|
||||
#[doc(alias = "BeginTooltip", alias = "EndTooltip", alias = "SetTooltip")]
|
||||
pub fn tooltip_text<T: AsRef<str>>(&self, text: T) {
|
||||
self.tooltip(|| self.text(text));
|
||||
}
|
||||
|
||||
@ -1,47 +1,87 @@
|
||||
use std::{
|
||||
ffi::{c_void, CStr},
|
||||
os::raw::{c_char, c_int},
|
||||
};
|
||||
use std::ffi::{c_char, c_void};
|
||||
|
||||
use crate::{
|
||||
internal::{ImVector, RawCast},
|
||||
Io, ViewportFlags,
|
||||
};
|
||||
use crate::{internal::RawCast, ViewportFlags};
|
||||
|
||||
/// Holds the information needed to enable multiple viewports.
|
||||
#[repr(C)]
|
||||
pub struct PlatformIo {
|
||||
pub(crate) get_clipboard_text_fn:
|
||||
Option<unsafe extern "C" fn(*mut sys::ImGuiContext) -> *const c_char>,
|
||||
|
||||
pub(crate) set_clipboard_text_fn:
|
||||
Option<unsafe extern "C" fn(*mut sys::ImGuiContext, *const c_char)>,
|
||||
|
||||
pub(crate) clipboard_user_data: *mut c_void,
|
||||
|
||||
pub(crate) open_in_shell_fn:
|
||||
Option<unsafe extern "C" fn(ctx: *mut sys::ImGuiContext, path: *const c_char) -> bool>,
|
||||
pub(crate) open_in_shell_user_data: *mut c_void,
|
||||
pub(crate) set_ime_data_fn: Option<
|
||||
unsafe extern "C" fn(
|
||||
ctx: *mut sys::ImGuiContext,
|
||||
viewport: *mut sys::ImGuiViewport,
|
||||
data: *mut sys::ImGuiPlatformImeData,
|
||||
),
|
||||
>,
|
||||
pub(crate) ime_user_data: *mut c_void,
|
||||
pub(crate) locale_decimal_point: sys::ImWchar,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_show_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_set_window_pos: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_get_window_pos: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_get_window_size: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_set_window_focus: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_get_window_focus: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_get_window_minimized: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_set_window_title:
|
||||
Option<unsafe extern "C" fn(*mut Viewport, *const c_char)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_set_window_alpha: Option<unsafe extern "C" fn(*mut Viewport, f32)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_update_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_get_window_dpi_scale: Option<unsafe extern "C" fn(*mut Viewport) -> f32>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_on_changed_viewport: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) platform_create_vk_surface:
|
||||
Option<unsafe extern "C" fn(*mut Viewport, u64, *const c_void, *mut u64) -> c_int>,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) renderer_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) renderer_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) renderer_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) renderer_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) renderer_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
|
||||
/// Holds information about the available monitors.
|
||||
/// Should be initialized and updated by the [`PlatformViewportBackend`].
|
||||
#[cfg(feature = "docking")]
|
||||
pub monitors: ImVector<PlatformMonitor>,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) viewports: ImVector<*mut Viewport>,
|
||||
}
|
||||
|
||||
@ -69,359 +109,44 @@ fn test_platform_io_memory_layout() {
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(platform_create_window, Platform_CreateWindow);
|
||||
assert_field_offset!(platform_destroy_window, Platform_DestroyWindow);
|
||||
assert_field_offset!(platform_show_window, Platform_ShowWindow);
|
||||
assert_field_offset!(platform_set_window_pos, Platform_SetWindowPos);
|
||||
assert_field_offset!(platform_get_window_pos, Platform_GetWindowPos);
|
||||
assert_field_offset!(platform_set_window_size, Platform_SetWindowSize);
|
||||
assert_field_offset!(platform_get_window_size, Platform_GetWindowSize);
|
||||
assert_field_offset!(platform_set_window_focus, Platform_SetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_focus, Platform_GetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_minimized, Platform_GetWindowMinimized);
|
||||
assert_field_offset!(platform_set_window_title, Platform_SetWindowTitle);
|
||||
assert_field_offset!(platform_set_window_alpha, Platform_SetWindowAlpha);
|
||||
assert_field_offset!(platform_update_window, Platform_UpdateWindow);
|
||||
assert_field_offset!(platform_render_window, Platform_RenderWindow);
|
||||
assert_field_offset!(platform_swap_buffers, Platform_SwapBuffers);
|
||||
assert_field_offset!(platform_get_window_dpi_scale, Platform_GetWindowDpiScale);
|
||||
assert_field_offset!(platform_on_changed_viewport, Platform_OnChangedViewport);
|
||||
assert_field_offset!(platform_create_vk_surface, Platform_CreateVkSurface);
|
||||
assert_field_offset!(get_clipboard_text_fn, Platform_GetClipboardTextFn);
|
||||
assert_field_offset!(set_clipboard_text_fn, Platform_SetClipboardTextFn);
|
||||
assert_field_offset!(clipboard_user_data, Platform_ClipboardUserData);
|
||||
assert_field_offset!(open_in_shell_fn, Platform_OpenInShellFn);
|
||||
assert_field_offset!(open_in_shell_user_data, Platform_OpenInShellUserData);
|
||||
assert_field_offset!(set_ime_data_fn, Platform_SetImeDataFn);
|
||||
assert_field_offset!(ime_user_data, Platform_ImeUserData);
|
||||
assert_field_offset!(locale_decimal_point, Platform_LocaleDecimalPoint);
|
||||
|
||||
assert_field_offset!(renderer_create_window, Renderer_CreateWindow);
|
||||
assert_field_offset!(renderer_destroy_window, Renderer_DestroyWindow);
|
||||
assert_field_offset!(renderer_set_window_size, Renderer_SetWindowSize);
|
||||
assert_field_offset!(renderer_render_window, Renderer_RenderWindow);
|
||||
assert_field_offset!(renderer_swap_buffers, Renderer_SwapBuffers);
|
||||
#[cfg(feature = "docking")]
|
||||
{
|
||||
assert_field_offset!(platform_create_window, Platform_CreateWindow);
|
||||
assert_field_offset!(platform_destroy_window, Platform_DestroyWindow);
|
||||
assert_field_offset!(platform_show_window, Platform_ShowWindow);
|
||||
assert_field_offset!(platform_set_window_pos, Platform_SetWindowPos);
|
||||
assert_field_offset!(platform_get_window_pos, Platform_GetWindowPos);
|
||||
assert_field_offset!(platform_set_window_size, Platform_SetWindowSize);
|
||||
assert_field_offset!(platform_get_window_size, Platform_GetWindowSize);
|
||||
assert_field_offset!(platform_set_window_focus, Platform_SetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_focus, Platform_GetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_minimized, Platform_GetWindowMinimized);
|
||||
assert_field_offset!(platform_set_window_title, Platform_SetWindowTitle);
|
||||
assert_field_offset!(platform_set_window_alpha, Platform_SetWindowAlpha);
|
||||
assert_field_offset!(platform_update_window, Platform_UpdateWindow);
|
||||
assert_field_offset!(platform_render_window, Platform_RenderWindow);
|
||||
assert_field_offset!(platform_swap_buffers, Platform_SwapBuffers);
|
||||
assert_field_offset!(platform_get_window_dpi_scale, Platform_GetWindowDpiScale);
|
||||
assert_field_offset!(platform_on_changed_viewport, Platform_OnChangedViewport);
|
||||
assert_field_offset!(platform_create_vk_surface, Platform_CreateVkSurface);
|
||||
|
||||
assert_field_offset!(monitors, Monitors);
|
||||
assert_field_offset!(viewports, Viewports);
|
||||
}
|
||||
assert_field_offset!(renderer_create_window, Renderer_CreateWindow);
|
||||
assert_field_offset!(renderer_destroy_window, Renderer_DestroyWindow);
|
||||
assert_field_offset!(renderer_set_window_size, Renderer_SetWindowSize);
|
||||
assert_field_offset!(renderer_render_window, Renderer_RenderWindow);
|
||||
assert_field_offset!(renderer_swap_buffers, Renderer_SwapBuffers);
|
||||
|
||||
/// Trait holding functions needed when the platform integration supports viewports.
|
||||
///
|
||||
/// Register it via [`Context::set_platform_backend()`](crate::context::Context::set_platform_backend())
|
||||
pub trait PlatformViewportBackend: 'static {
|
||||
/// Called by imgui when a new [`Viewport`] is created.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the creation of a platform window.
|
||||
/// The window should be invisible.
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui when a [`Viewport`] is about to be destroyed.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the destruction of the platform window.
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to make a [`Viewport`] visible.
|
||||
fn show_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to reposition a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `pos` specifies the position of the windows content area (excluding title bar etc.)
|
||||
fn set_window_pos(&mut self, viewport: &mut Viewport, pos: [f32; 2]);
|
||||
/// Called by imgui to get the position of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// You should return the position of the window's content area (excluding title bar etc.)
|
||||
fn get_window_pos(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to set the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `size` specifies the size of the window's content area (excluding title bar etc.)
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
/// Called by imgui to get the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// you should return the size of the window's content area (excluding title bar etc.)
|
||||
fn get_window_size(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to make a [`Viewport`] steal the focus.
|
||||
fn set_window_focus(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to query whether a [`Viewport`] is in focus.
|
||||
fn get_window_focus(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to query whether a [`Viewport`] is minimized.
|
||||
fn get_window_minimized(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to set a [`Viewport`] title.
|
||||
fn set_window_title(&mut self, viewport: &mut Viewport, title: &str);
|
||||
/// Called by imgui to set the opacity of an entire [`Viewport`].
|
||||
///
|
||||
/// If your backend does not support opactiy, it is safe to just do nothing in this function.
|
||||
fn set_window_alpha(&mut self, viewport: &mut Viewport, alpha: f32);
|
||||
fn update_window(&mut self, viewport: &mut Viewport);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
fn create_vk_surface(
|
||||
&mut self,
|
||||
viewport: &mut Viewport,
|
||||
instance: u64,
|
||||
out_surface: &mut u64,
|
||||
) -> i32;
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`PlatformViewportContext`].
|
||||
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_platform_user_data
|
||||
as *mut PlatformViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`RendererViewportContext`].
|
||||
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_renderer_user_data
|
||||
as *mut RendererViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.create_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.destroy_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_show_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.show_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_pos(viewport: *mut Viewport, pos: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_pos(unsafe { &mut *viewport }, [pos.x, pos.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_pos(
|
||||
viewport: *mut Viewport,
|
||||
out_pos: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let pos = ctx.backend.get_window_pos(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_pos = sys::ImVec2::new(pos[0], pos[1]);
|
||||
}
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_size(
|
||||
viewport: *mut Viewport,
|
||||
out_size: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let size = ctx.backend.get_window_size(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_size = sys::ImVec2::new(size[0], size[1]);
|
||||
}
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_focus(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_focus(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_focus(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_focus(unsafe { &mut *viewport })
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_minimized(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_minimized(unsafe { &mut *viewport })
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_title(viewport: *mut Viewport, title: *const c_char) {
|
||||
let ctx = get_platform_ctx();
|
||||
let title = unsafe { CStr::from_ptr(title).to_str().unwrap() };
|
||||
ctx.backend
|
||||
.set_window_title(unsafe { &mut *viewport }, title);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_alpha(viewport: *mut Viewport, alpha: f32) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.set_window_alpha(unsafe { &mut *viewport }, alpha);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_update_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.update_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.render_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.swap_buffers(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn platform_create_vk_surface(
|
||||
viewport: *mut Viewport,
|
||||
instance: u64,
|
||||
_arg: *const c_void,
|
||||
out_surface: *mut u64,
|
||||
) -> c_int {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend
|
||||
.create_vk_surface(unsafe { &mut *viewport }, instance, unsafe {
|
||||
&mut *out_surface
|
||||
})
|
||||
}
|
||||
|
||||
/// The default [`PlatformViewportBackend`], does nothing.
|
||||
pub(crate) struct DummyPlatformViewportBackend {}
|
||||
impl PlatformViewportBackend for DummyPlatformViewportBackend {
|
||||
fn create_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn show_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_pos(&mut self, _viewport: &mut Viewport, _pos: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_pos(&mut self, _viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, _viewport: &mut Viewport, _size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_size(&mut self, _viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_focus(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_focus(&mut self, _viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_minimized(&mut self, _viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_title(&mut self, _viewport: &mut Viewport, _title: &str) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_alpha(&mut self, _viewport: &mut Viewport, _alpha: f32) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn update_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_vk_surface(
|
||||
&mut self,
|
||||
_viewport: &mut Viewport,
|
||||
_instance: u64,
|
||||
_out_surface: &mut u64,
|
||||
) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`PlatformViewportBackend`].
|
||||
pub(crate) struct PlatformViewportContext {
|
||||
pub(crate) backend: Box<dyn PlatformViewportBackend>,
|
||||
}
|
||||
|
||||
impl PlatformViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyPlatformViewportBackend {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that holds optional functions for a rendering backend to support multiple viewports.
|
||||
///
|
||||
/// It is completely fine to not use this Backend at all, as all functions are optional.
|
||||
pub trait RendererViewportBackend: 'static {
|
||||
/// Called after [`PlatformViewportBackend::create_window()`].
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called before [`PlatformViewportBackend::destroy_window()`].
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called after [`PlatformViewportBackend::set_window_size()`].
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn renderer_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.create_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.destroy_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend
|
||||
.set_window_size(unsafe { &mut *viewport }, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.render_window(unsafe { &mut *viewport });
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.swap_buffers(unsafe { &mut *viewport });
|
||||
}
|
||||
|
||||
/// The default [`RendererViewportBackend`], does nothing.
|
||||
pub(crate) struct DummyRendererViewportBackend {}
|
||||
impl RendererViewportBackend for DummyRendererViewportBackend {
|
||||
fn create_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, _viewport: &mut Viewport, _size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, _viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`RendererViewportBackend`].
|
||||
pub(crate) struct RendererViewportContext {
|
||||
pub(crate) backend: Box<dyn RendererViewportBackend>,
|
||||
}
|
||||
|
||||
impl RendererViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyRendererViewportBackend {}),
|
||||
}
|
||||
assert_field_offset!(monitors, Monitors);
|
||||
assert_field_offset!(viewports, Viewports);
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,20 +161,31 @@ pub struct Viewport {
|
||||
pub size: [f32; 2],
|
||||
pub work_pos: [f32; 2],
|
||||
pub work_size: [f32; 2],
|
||||
pub dpi_scale: f32,
|
||||
pub(crate) parent_viewport_id: crate::Id,
|
||||
pub(crate) draw_data: *mut crate::DrawData,
|
||||
|
||||
pub renderer_user_data: *mut c_void,
|
||||
pub platform_user_data: *mut c_void,
|
||||
pub platform_handle: *mut c_void,
|
||||
pub platform_handle_raw: *mut c_void,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub dpi_scale: f32,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) parent_viewport_id: crate::Id,
|
||||
#[cfg(feature = "docking")]
|
||||
pub(crate) draw_data: *mut crate::DrawData,
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
pub renderer_user_data: *mut c_void,
|
||||
#[cfg(feature = "docking")]
|
||||
pub platform_user_data: *mut c_void,
|
||||
#[cfg(feature = "docking")]
|
||||
pub platform_window_created: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub platform_request_move: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub platform_request_resize: bool,
|
||||
#[cfg(feature = "docking")]
|
||||
pub platform_request_close: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
impl Viewport {
|
||||
/// Returns the draw data of the respective Viewport.
|
||||
pub fn draw_data(&self) -> &crate::DrawData {
|
||||
@ -485,74 +221,20 @@ fn test_viewport_memory_layout() {
|
||||
assert_field_offset!(size, Size);
|
||||
assert_field_offset!(work_pos, WorkPos);
|
||||
assert_field_offset!(work_size, WorkSize);
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
assert_field_offset!(parent_viewport_id, ParentViewportId);
|
||||
assert_field_offset!(draw_data, DrawData);
|
||||
|
||||
assert_field_offset!(renderer_user_data, RendererUserData);
|
||||
assert_field_offset!(platform_user_data, PlatformUserData);
|
||||
assert_field_offset!(platform_handle, PlatformHandle);
|
||||
assert_field_offset!(platform_handle_raw, PlatformHandleRaw);
|
||||
assert_field_offset!(platform_window_created, PlatformWindowCreated);
|
||||
assert_field_offset!(platform_request_move, PlatformRequestMove);
|
||||
assert_field_offset!(platform_request_resize, PlatformRequestResize);
|
||||
assert_field_offset!(platform_request_close, PlatformRequestClose);
|
||||
}
|
||||
|
||||
/// Describes a monitor that can be used by ImGui.
|
||||
#[repr(C)]
|
||||
pub struct PlatformMonitor {
|
||||
/// Position of the monitor on the virtual desktop.
|
||||
pub main_pos: [f32; 2],
|
||||
/// Size of the monitor on the virtual desktop.
|
||||
pub main_size: [f32; 2],
|
||||
/// Working position of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `main_pos` if not known.
|
||||
pub work_pos: [f32; 2],
|
||||
/// Working size of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `work_size` if not known.
|
||||
pub work_size: [f32; 2],
|
||||
pub dpi_scale: f32,
|
||||
}
|
||||
#[cfg(feature = "docking")]
|
||||
{
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
assert_field_offset!(parent_viewport_id, ParentViewportId);
|
||||
assert_field_offset!(draw_data, DrawData);
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_platform_monitor_memory_layout() {
|
||||
use std::mem;
|
||||
assert_eq!(
|
||||
mem::size_of::<PlatformMonitor>(),
|
||||
mem::size_of::<sys::ImGuiPlatformMonitor>()
|
||||
);
|
||||
assert_eq!(
|
||||
mem::align_of::<PlatformMonitor>(),
|
||||
mem::align_of::<sys::ImGuiPlatformMonitor>()
|
||||
);
|
||||
use sys::ImGuiPlatformMonitor;
|
||||
macro_rules! assert_field_offset {
|
||||
($l:ident, $r:ident) => {
|
||||
assert_eq!(
|
||||
memoffset::offset_of!(PlatformMonitor, $l),
|
||||
memoffset::offset_of!(ImGuiPlatformMonitor, $r)
|
||||
);
|
||||
};
|
||||
assert_field_offset!(renderer_user_data, RendererUserData);
|
||||
assert_field_offset!(platform_user_data, PlatformUserData);
|
||||
assert_field_offset!(platform_window_created, PlatformWindowCreated);
|
||||
assert_field_offset!(platform_request_move, PlatformRequestMove);
|
||||
assert_field_offset!(platform_request_resize, PlatformRequestResize);
|
||||
assert_field_offset!(platform_request_close, PlatformRequestClose);
|
||||
}
|
||||
|
||||
assert_field_offset!(main_pos, MainPos);
|
||||
assert_field_offset!(main_size, MainSize);
|
||||
assert_field_offset!(work_pos, WorkPos);
|
||||
assert_field_offset!(work_size, WorkSize);
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowPos(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowSize(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
}
|
||||
|
||||
@ -112,11 +112,6 @@ impl<'ui, 'p, Label: AsRef<str>> PopupModal<'ui, 'p, Label> {
|
||||
.set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
|
||||
self
|
||||
}
|
||||
pub fn always_use_window_padding(mut self, value: bool) -> Self {
|
||||
self.flags
|
||||
.set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
|
||||
self
|
||||
}
|
||||
|
||||
/// Consume and draw the PopupModal.
|
||||
/// Returns the result of the closure, if it is called.
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::mem::size_of;
|
||||
use std::slice;
|
||||
|
||||
use crate::internal::{RawCast, RawWrapper};
|
||||
use crate::internal::{ImVector, RawCast, RawWrapper};
|
||||
use crate::math::MintVec2;
|
||||
use crate::render::renderer::TextureId;
|
||||
use crate::sys;
|
||||
@ -18,7 +17,7 @@ pub struct DrawData {
|
||||
/// For convenience, sum of all draw list vertex buffer sizes.
|
||||
pub total_vtx_count: i32,
|
||||
// Array of DrawList.
|
||||
cmd_lists: *mut *mut DrawList,
|
||||
cmd_lists: ImVector<DrawList>,
|
||||
/// Upper-left position of the viewport to render.
|
||||
///
|
||||
/// (= upper-left corner of the orthogonal projection matrix to use)
|
||||
@ -33,7 +32,7 @@ pub struct DrawData {
|
||||
/// [2.0, 2.0] on Retina displays, but fractional values are also possible.
|
||||
pub framebuffer_scale: [f32; 2],
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
/// Viewport carrying the DrawData instance, might be of use to the renderer (generally not).
|
||||
owner_viewport: *mut sys::ImGuiViewport,
|
||||
}
|
||||
|
||||
@ -56,11 +55,11 @@ impl DrawData {
|
||||
}
|
||||
#[inline]
|
||||
pub(crate) unsafe fn cmd_lists(&self) -> &[*const DrawList] {
|
||||
if self.cmd_lists_count <= 0 || self.cmd_lists.is_null() {
|
||||
if self.cmd_lists_count <= 0 || self.cmd_lists.data.is_null() {
|
||||
return &[];
|
||||
}
|
||||
slice::from_raw_parts(
|
||||
self.cmd_lists as *const *const DrawList,
|
||||
self.cmd_lists.data as *const *const DrawList,
|
||||
self.cmd_lists_count as usize,
|
||||
)
|
||||
}
|
||||
@ -332,13 +331,6 @@ impl OwnedDrawData {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
unsafe fn copy_docking_properties(source: &sys::ImDrawData, dest: *mut sys::ImDrawData) {
|
||||
(*dest).OwnerViewport = source.OwnerViewport;
|
||||
}
|
||||
#[cfg(not(feature = "docking"))]
|
||||
unsafe fn copy_docking_properties(_source: &sys::ImDrawData, _dest: *mut sys::ImDrawData) {}
|
||||
}
|
||||
|
||||
impl Default for OwnedDrawData {
|
||||
@ -364,16 +356,12 @@ impl From<&DrawData> for OwnedDrawData {
|
||||
(*result).DisplayPos = other_ptr.DisplayPos;
|
||||
(*result).DisplaySize = other_ptr.DisplaySize;
|
||||
(*result).FramebufferScale = other_ptr.FramebufferScale;
|
||||
(*result).CmdListsCount = other_ptr.CmdListsCount;
|
||||
(*result).CmdLists = sys::igMemAlloc(
|
||||
size_of::<*mut sys::ImDrawList>() * other_ptr.CmdListsCount as usize,
|
||||
) as *mut *mut sys::ImDrawList;
|
||||
OwnedDrawData::copy_docking_properties(other_ptr, result);
|
||||
(*result).OwnerViewport = other_ptr.OwnerViewport;
|
||||
|
||||
let mut current_draw_list = (*result).CmdLists;
|
||||
(*result).CmdListsCount = 0;
|
||||
for i in 0..other_ptr.CmdListsCount as usize {
|
||||
*current_draw_list = sys::ImDrawList_CloneOutput(*other_ptr.CmdLists.add(i));
|
||||
current_draw_list = current_draw_list.add(1);
|
||||
sys::ImDrawData_AddDrawList(result, *other_ptr.CmdLists.Data.add(i));
|
||||
(*result).CmdListsCount += 1;
|
||||
}
|
||||
result
|
||||
},
|
||||
@ -386,14 +374,14 @@ impl Drop for OwnedDrawData {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if !self.draw_data.is_null() {
|
||||
if !(*self.draw_data).CmdLists.is_null() {
|
||||
if !(*self.draw_data).CmdLists.Data.is_null() {
|
||||
for i in 0..(*self.draw_data).CmdListsCount as usize {
|
||||
let ptr = *(*self.draw_data).CmdLists.add(i);
|
||||
let ptr = *(*self.draw_data).CmdLists.Data.add(i);
|
||||
if !ptr.is_null() {
|
||||
sys::ImDrawList_destroy(ptr);
|
||||
}
|
||||
}
|
||||
sys::igMemFree((*self.draw_data).CmdLists as *mut std::ffi::c_void);
|
||||
sys::igMemFree((*self.draw_data).CmdLists.Data as *mut std::ffi::c_void);
|
||||
}
|
||||
sys::ImDrawData_destroy(self.draw_data);
|
||||
self.draw_data = std::ptr::null_mut();
|
||||
@ -420,13 +408,16 @@ fn test_owneddrawdata_from_drawdata() {
|
||||
let draw_data_raw = sys::ImDrawData {
|
||||
Valid: true,
|
||||
CmdListsCount: 1,
|
||||
CmdLists: draw_lists_raw.as_mut_ptr(),
|
||||
CmdLists: sys::ImVector_ImDrawListPtr {
|
||||
Size: 1,
|
||||
Capacity: 1,
|
||||
Data: draw_lists_raw.as_mut_ptr(),
|
||||
},
|
||||
TotalIdxCount: 123,
|
||||
TotalVtxCount: 456,
|
||||
DisplayPos: sys::ImVec2 { x: 123.0, y: 456.0 },
|
||||
DisplaySize: sys::ImVec2 { x: 789.0, y: 012.0 },
|
||||
FramebufferScale: sys::ImVec2 { x: 3.0, y: 7.0 },
|
||||
#[cfg(feature = "docking")]
|
||||
OwnerViewport: unsafe { std::ptr::null_mut::<sys::ImGuiViewport>().offset(123) },
|
||||
};
|
||||
let draw_data = unsafe { DrawData::from_raw(&draw_data_raw) };
|
||||
@ -441,7 +432,7 @@ fn test_owneddrawdata_from_drawdata() {
|
||||
draw_data_raw.CmdListsCount,
|
||||
owned_draw_data_raw.CmdListsCount
|
||||
);
|
||||
assert!(!draw_data_raw.CmdLists.is_null());
|
||||
assert!(!draw_data_raw.CmdLists.Data.is_null());
|
||||
assert_eq!(
|
||||
draw_data_raw.TotalIdxCount,
|
||||
owned_draw_data_raw.TotalIdxCount
|
||||
@ -463,37 +454,3 @@ fn test_owneddrawdata_from_drawdata() {
|
||||
owned_draw_data_raw.OwnerViewport
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_owneddrawdata_drop() {
|
||||
let (_guard, _ctx) = crate::test::test_ctx();
|
||||
let initial_allocation_count = unsafe { (*sys::igGetIO()).MetricsActiveAllocations };
|
||||
|
||||
// Build a dummy draw data object
|
||||
let mut draw_list = sys::ImDrawList::default();
|
||||
let mut draw_lists_raw = [std::ptr::addr_of_mut!(draw_list)];
|
||||
let draw_data_raw = sys::ImDrawData {
|
||||
Valid: true,
|
||||
CmdListsCount: 1,
|
||||
CmdLists: draw_lists_raw.as_mut_ptr(),
|
||||
TotalIdxCount: 0,
|
||||
TotalVtxCount: 0,
|
||||
DisplayPos: sys::ImVec2 { x: 0.0, y: 0.0 },
|
||||
DisplaySize: sys::ImVec2 { x: 800.0, y: 600.0 },
|
||||
FramebufferScale: sys::ImVec2 { x: 1.0, y: 1.0 },
|
||||
#[cfg(feature = "docking")]
|
||||
OwnerViewport: std::ptr::null_mut(),
|
||||
};
|
||||
let draw_data = unsafe { DrawData::from_raw(&draw_data_raw) };
|
||||
|
||||
// Clone it, then drop it, and ensure all allocations are returned
|
||||
{
|
||||
let _owned_draw_data: OwnedDrawData = draw_data.into();
|
||||
let cloned_allocation_count = unsafe { (*sys::igGetIO()).MetricsActiveAllocations };
|
||||
assert!(cloned_allocation_count > initial_allocation_count);
|
||||
// owned_draw_data is dropped here...
|
||||
}
|
||||
let final_allocation_count = unsafe { (*sys::igGetIO()).MetricsActiveAllocations };
|
||||
assert_eq!(initial_allocation_count, final_allocation_count);
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ use crate::math::MintVec4;
|
||||
use crate::style::{StyleColor, StyleVar};
|
||||
use crate::sys;
|
||||
use crate::Ui;
|
||||
use std::mem;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
/// # Parameter stacks (shared)
|
||||
@ -239,60 +238,42 @@ impl Ui {
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Deprecated since `0.13.0`, use [`Ui::push_item_flag`] with [`ItemFlag::NO_TAB_STOP`]
|
||||
/// instead.
|
||||
#[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.
|
||||
///
|
||||
/// Returns a `ItemFlagsStackToken` that may be popped by calling `.pop()`
|
||||
///
|
||||
/// ## 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"
|
||||
since = "0.13.0",
|
||||
note = "use `Ui::push_item_flag` with `ItemFlag::NO_TAB_STOP`"
|
||||
)]
|
||||
pub fn push_item_flag(&self, item_flag: ItemFlag) -> ItemFlagsStackToken<'_> {
|
||||
use self::ItemFlag::*;
|
||||
match item_flag {
|
||||
AllowKeyboardFocus(v) => unsafe { sys::igPushAllowKeyboardFocus(v) },
|
||||
ButtonRepeat(v) => unsafe { sys::igPushButtonRepeat(v) },
|
||||
}
|
||||
ItemFlagsStackToken::new(self, item_flag)
|
||||
pub fn push_allow_keyboard_focus(&self, tab_stop: bool) -> ItemFlagsStackToken<'_> {
|
||||
self.push_item_flag(ItemFlag::NO_TAB_STOP, !tab_stop)
|
||||
}
|
||||
}
|
||||
|
||||
/// A temporary change in item flags
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ItemFlag {
|
||||
AllowKeyboardFocus(bool),
|
||||
ButtonRepeat(bool),
|
||||
/// Any button-like behavior will have repeat mode enabled
|
||||
///
|
||||
/// Deprecated since `0.13.0`, use [`Ui::push_item_flag`] with [`ItemFlag::BUTTON_REPEAT`]
|
||||
/// instead.
|
||||
#[doc(alias = "PushButtonRepeat")]
|
||||
#[deprecated(
|
||||
since = "0.13.0",
|
||||
note = "use `Ui::push_item_flag` with `ItemFlag::BUTTON_REPEAT`"
|
||||
)]
|
||||
pub fn push_button_repeat(&self, value: bool) -> ItemFlagsStackToken<'_> {
|
||||
self.push_item_flag(ItemFlag::BUTTON_REPEAT, value)
|
||||
}
|
||||
|
||||
/// Changes an item flag by pushing a change to the item flag stack and a boolean
|
||||
/// on whether to enable or disable the flag.
|
||||
///
|
||||
/// Returns a `ItemFlagsStackToken` that may be popped by calling `.pop()` or dropping it.
|
||||
pub fn push_item_flag(&self, item_flag: ItemFlag, enabled: bool) -> ItemFlagsStackToken<'_> {
|
||||
unsafe {
|
||||
sys::igPushItemFlag(item_flag.bits() as i32, enabled);
|
||||
}
|
||||
|
||||
ItemFlagsStackToken::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
create_token!(
|
||||
@ -309,56 +290,16 @@ create_token!(
|
||||
drop { sys::igPopTextWrapPos() }
|
||||
);
|
||||
|
||||
create_token!(
|
||||
pub struct PushAllowKeyboardFocusToken<'ui>;
|
||||
crate::create_token!(
|
||||
/// Tracks a change made with [`Ui::push_item_flag`] that can be popped
|
||||
/// by calling [`ItemFlagsStackToken::end`] or dropping.
|
||||
pub struct ItemFlagsStackToken<'ui>;
|
||||
|
||||
#[doc(alias = "PopAllowKeyboardFocus")]
|
||||
drop { sys::igPopAllowKeyboardFocus() }
|
||||
/// Pops an [`ItemFlag`] made with [`Ui::push_item_flag`].
|
||||
#[doc(alias = "PopItemFlag")]
|
||||
drop { sys::igPopItemFlag() }
|
||||
);
|
||||
|
||||
create_token!(
|
||||
pub struct PushButtonRepeatToken<'ui>;
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ItemFlagsStackToken<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.1 == mem::discriminant(&ItemFlag::AllowKeyboardFocus(true)) {
|
||||
sys::igPopAllowKeyboardFocus();
|
||||
} else if self.1 == mem::discriminant(&ItemFlag::ButtonRepeat(true)) {
|
||||
sys::igPopButtonRepeat();
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create_token!(
|
||||
/// Tracks an ID pushed to the ID stack that can be popped by calling `.pop()`
|
||||
/// or by dropping. See [`crate::Ui::push_id`] for more details.
|
||||
@ -509,3 +450,25 @@ impl Ui {
|
||||
IdStackToken::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// A temporary change in item flags, used in [`Ui::push_item_flag`].
|
||||
pub struct ItemFlag: u32 {
|
||||
/// Disable keyboard tabbing. This is a "lighter" version of [`ItemFlag::NO_NAV`].
|
||||
const NO_TAB_STOP = sys::ImGuiItemFlags_NoTabStop;
|
||||
/// Disable any form of focusing (keyboard/gamepad directional navigation and
|
||||
/// [`Ui::set_keyboard_focus_here`] calls).
|
||||
const NO_NAV = sys::ImGuiItemFlags_NoNav;
|
||||
/// Disable item being a candidate for default focus (e.g. used by title bar items).
|
||||
const NO_NAV_DEFAULT_FOCUS = sys::ImGuiItemFlags_NoNavDefaultFocus;
|
||||
/// Any button-like behavior will have repeat mode enabled (based on [`Io::key_repeat_delay`](crate::Io::key_repeat_delay)
|
||||
/// and [`Io::key_repeat_rate`](crate::Io::key_repeat_rate) values).
|
||||
/// Note that you can also call [`Ui::is_item_active`] after any button to tell if it is being held.
|
||||
const BUTTON_REPEAT = sys::ImGuiItemFlags_ButtonRepeat;
|
||||
/// [`Ui::menu_item`]/[`Ui::selectable`] automatically close their parent popup window.
|
||||
const AUTO_CLOSE_POPUPS = sys::ImGuiItemFlags_AutoClosePopups;
|
||||
/// Allow submitting an item with the same identifier as an item already submitted this frame without triggering
|
||||
/// a warning tooltip if [`Io::config_debug_highlight_id_conflicts`](crate::Io::config_debug_highlight_id_conflicts) is set.
|
||||
const ALLOW_DUPLICATE_ID = sys::ImGuiItemFlags_AllowDuplicateId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ use std::fmt;
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
use crate::internal::RawCast;
|
||||
use crate::sys;
|
||||
use crate::Direction;
|
||||
use crate::{sys, HoveredFlags};
|
||||
|
||||
/// User interface style/colors
|
||||
#[repr(C)]
|
||||
@ -103,6 +103,19 @@ pub struct Style {
|
||||
/// `= 0.0`: always show when hovering
|
||||
/// `= f32::MAX`: never show close button unless selected
|
||||
pub tab_min_width_for_close_button: f32,
|
||||
|
||||
/// Thickness of tab-bar separator, which takes on the tab active color to denote focus.
|
||||
pub tab_bar_border_size: f32,
|
||||
|
||||
/// Thickness of tab-bar overline, which highlights the selected tab-bar.
|
||||
pub tab_bar_overline_size: f32,
|
||||
|
||||
/// Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees).
|
||||
pub table_angled_headers_angle: f32,
|
||||
|
||||
/// Alignment of angled headers within the cell
|
||||
pub table_angled_headers_text_align: [f32; 2],
|
||||
|
||||
/// Side of the color buttonton pubin color editor widgets (left/right).
|
||||
pub color_button_position: Direction,
|
||||
/// Alignment of button text when button is larger than text.
|
||||
@ -113,6 +126,14 @@ pub struct Style {
|
||||
///
|
||||
/// Defaults to [0.5, 0.5] (top-left aligned).
|
||||
pub selectable_text_align: [f32; 2],
|
||||
/// Thickkness of border in [`Ui::separator_with_text`](crate::Ui::separator_with_text)
|
||||
pub separator_text_border_size: f32,
|
||||
/// Alignment of text within the separator. Defaults to `[0.0, 0.5]` (left aligned, center).
|
||||
pub separator_text_align: [f32; 2],
|
||||
/// Horizontal offset of text from each edge of the separator + spacing on other axis.
|
||||
/// Generally small values. .y is recommended to be == [`StyleVar::FramePadding`].y.
|
||||
pub separator_text_padding: [f32; 2],
|
||||
|
||||
/// Window positions are clamped to be visible within the display area or monitors by at least
|
||||
/// this amount.
|
||||
///
|
||||
@ -149,8 +170,28 @@ pub struct Style {
|
||||
///
|
||||
/// Decrease for higher quality but more geometry.
|
||||
pub circle_tesselation_max_error: f32,
|
||||
|
||||
/// Style colors.
|
||||
pub colors: [[f32; 4]; StyleColor::COUNT],
|
||||
|
||||
/// Delay on hover before
|
||||
/// [`Ui::is_item_hovered_with_flags`](crate::Ui::is_item_hovered_with_flags) + [`HoveredFlags::STATIONARY`] returns true
|
||||
pub hover_stationary_delay: f32,
|
||||
|
||||
/// Delay on hover before
|
||||
/// [`Ui::is_item_hovered_with_flags`](crate::Ui::is_item_hovered_with_flags) + [`HoveredFlags::DELAY_SHORT`] returns true
|
||||
pub hover_delay_short: f32,
|
||||
|
||||
/// Delay on hover before
|
||||
/// [`Ui::is_item_hovered_with_flags`](crate::Ui::is_item_hovered_with_flags) + [`HoveredFlags::DELAY_NORMAL`] returns true
|
||||
pub hover_delay_normal: f32,
|
||||
|
||||
/// Default flags when using [`HoveredFlags::FOR_TOOLTIP`] or [`Ui::begin_tooltip`](crate::Ui::begin_tooltip)
|
||||
/// or [`Ui::tooltip_text`](crate::Ui::tooltip_text) while using mouse.
|
||||
pub hover_flags_for_tooltip_mouse: HoveredFlags,
|
||||
/// Default flags when using [`HoveredFlags::FOR_TOOLTIP`] or [`Ui::begin_tooltip`](crate::Ui::begin_tooltip)
|
||||
/// or [`Ui::tooltip_text`](crate::Ui::tooltip_text) while using keyboard/gamepad.
|
||||
pub hover_flags_for_tooltip_nav: HoveredFlags,
|
||||
}
|
||||
|
||||
unsafe impl RawCast<sys::ImGuiStyle> for Style {}
|
||||
@ -280,24 +321,26 @@ pub enum StyleColor {
|
||||
ResizeGripHovered = sys::ImGuiCol_ResizeGripHovered,
|
||||
/// Resize handle when mouse button down
|
||||
ResizeGripActive = sys::ImGuiCol_ResizeGripActive,
|
||||
/// Inactive tab color. Applies to both tab widgets and docked windows
|
||||
Tab = sys::ImGuiCol_Tab,
|
||||
/// Hovered tab (applies regardless if tab is active, or is in the active window)
|
||||
TabHovered = sys::ImGuiCol_TabHovered,
|
||||
/// Inactive tab color. Applies to both tab widgets and docked windows
|
||||
Tab = sys::ImGuiCol_Tab,
|
||||
/// Color of currently selected tab
|
||||
TabActive = sys::ImGuiCol_TabActive,
|
||||
TabSelected = sys::ImGuiCol_TabSelected,
|
||||
/// Tab horizontal overline, when tab-bar is focused & tab is selected
|
||||
TabSelectedOverline = sys::ImGuiCol_TabSelectedOverline,
|
||||
/// Non-selected, when in an unfocused window
|
||||
TabUnfocused = sys::ImGuiCol_TabUnfocused,
|
||||
TabDimmed = sys::ImGuiCol_TabDimmed,
|
||||
/// Selected tab, in an unfocused window
|
||||
TabUnfocusedActive = sys::ImGuiCol_TabUnfocusedActive,
|
||||
|
||||
TabDimmedSelected = sys::ImGuiCol_TabDimmedSelected,
|
||||
/// Non-selected, when in an unfocused window
|
||||
TabDimmedSelectedOverline = sys::ImGuiCol_TabDimmedSelectedOverline,
|
||||
/// Color of widget which appears when moving windows around, allowing splitting/etc of dock areas
|
||||
#[cfg(feature = "docking")]
|
||||
DockingPreview = sys::ImGuiCol_DockingPreview,
|
||||
/// Colour when black area is present in docking setup (e.g while dragging a window away from a split area, leaving it temporarily empty)
|
||||
#[cfg(feature = "docking")]
|
||||
DockingEmptyBg = sys::ImGuiCol_DockingEmptyBg,
|
||||
|
||||
/// Lines in [`crate::Ui::plot_lines`]
|
||||
PlotLines = sys::ImGuiCol_PlotLines,
|
||||
/// `PlotLines` when hovered
|
||||
@ -306,7 +349,6 @@ pub enum StyleColor {
|
||||
PlotHistogram = sys::ImGuiCol_PlotHistogram,
|
||||
/// `PlotHistogram` when hovered
|
||||
PlotHistogramHovered = sys::ImGuiCol_PlotHistogramHovered,
|
||||
|
||||
/// Background color of header rows in table widget
|
||||
TableHeaderBg = sys::ImGuiCol_TableHeaderBg,
|
||||
/// Main border color for table, used around whole table and around header cells
|
||||
@ -317,10 +359,10 @@ pub enum StyleColor {
|
||||
TableRowBg = sys::ImGuiCol_TableRowBg,
|
||||
/// Used for alternating row colors, if enabled by `TableFlags::ROW_BG`
|
||||
TableRowBgAlt = sys::ImGuiCol_TableRowBgAlt,
|
||||
|
||||
/// Hyperlink color
|
||||
TextLink = sys::ImGuiCol_TextLink,
|
||||
/// The highlight color used for selection in text inputs
|
||||
TextSelectedBg = sys::ImGuiCol_TextSelectedBg,
|
||||
|
||||
/// Used for drag-and-drop system
|
||||
DragDropTarget = sys::ImGuiCol_DragDropTarget,
|
||||
/// Gamepad/keyboard: current highlighted item
|
||||
@ -369,11 +411,13 @@ impl StyleColor {
|
||||
StyleColor::ResizeGrip,
|
||||
StyleColor::ResizeGripHovered,
|
||||
StyleColor::ResizeGripActive,
|
||||
StyleColor::Tab,
|
||||
StyleColor::TabHovered,
|
||||
StyleColor::TabActive,
|
||||
StyleColor::TabUnfocused,
|
||||
StyleColor::TabUnfocusedActive,
|
||||
StyleColor::Tab,
|
||||
StyleColor::TabSelected,
|
||||
StyleColor::TabSelectedOverline,
|
||||
StyleColor::TabDimmed,
|
||||
StyleColor::TabDimmedSelected,
|
||||
StyleColor::TabDimmedSelectedOverline,
|
||||
#[cfg(feature = "docking")]
|
||||
StyleColor::DockingPreview,
|
||||
#[cfg(feature = "docking")]
|
||||
@ -387,6 +431,7 @@ impl StyleColor {
|
||||
StyleColor::TableBorderLight,
|
||||
StyleColor::TableRowBg,
|
||||
StyleColor::TableRowBgAlt,
|
||||
StyleColor::TextLink,
|
||||
StyleColor::TextSelectedBg,
|
||||
StyleColor::DragDropTarget,
|
||||
StyleColor::NavHighlight,
|
||||
@ -438,9 +483,9 @@ impl StyleColor {
|
||||
StyleColor::ResizeGripActive => "ResizeGripActive",
|
||||
StyleColor::Tab => "Tab",
|
||||
StyleColor::TabHovered => "TabHovered",
|
||||
StyleColor::TabActive => "TabActive",
|
||||
StyleColor::TabUnfocused => "TabUnfocused",
|
||||
StyleColor::TabUnfocusedActive => "TabUnfocusedActive",
|
||||
StyleColor::TabSelected => "TabSelected",
|
||||
StyleColor::TabDimmed => "TabDimmed",
|
||||
StyleColor::TabDimmedSelected => "TabDimmedSelected",
|
||||
StyleColor::PlotLines => "PlotLines",
|
||||
StyleColor::PlotLinesHovered => "PlotLinesHovered",
|
||||
StyleColor::PlotHistogram => "PlotHistogram",
|
||||
@ -460,6 +505,9 @@ impl StyleColor {
|
||||
StyleColor::DockingPreview => "DockingPreview",
|
||||
#[cfg(feature = "docking")]
|
||||
StyleColor::DockingEmptyBg => "DockingEmptyBg",
|
||||
StyleColor::TabSelectedOverline => "TabSelectedOverline",
|
||||
StyleColor::TabDimmedSelectedOverline => "TabDimmedSelectedOverline",
|
||||
StyleColor::TextLink => "TextLink",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#![allow(clippy::float_cmp)]
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
use crate::input::mouse::MouseButton;
|
||||
@ -7,22 +8,77 @@ use crate::style::StyleColor;
|
||||
use crate::sys;
|
||||
use crate::Style;
|
||||
use crate::Ui;
|
||||
|
||||
bitflags! {
|
||||
/// Item hover check option flags
|
||||
/// Flags for [`Ui::is_item_hovered`], [`Ui::is_window_hovered`]
|
||||
/// Note: if you are trying to check whether your mouse should be dispatched to
|
||||
/// `Dear ImGui` or to your app, you should use [`Io::want_capture_mouse`](crate::Io::want_capture_mouse)
|
||||
/// instead! Please read the FAQ!
|
||||
///
|
||||
/// Note: windows with the [`WindowFlags::NO_INPUTS`](crate::WindowFlags::NO_INPUTS) flag
|
||||
/// are ignored by [`Ui::is_window_hovered`] calls.
|
||||
///
|
||||
/// Note: [`HoveredFlags::empty`] will return true in the above functions
|
||||
/// if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
|
||||
#[repr(transparent)]
|
||||
pub struct ItemHoveredFlags: u32 {
|
||||
/// Return true even if a popup window is blocking access to this item
|
||||
pub struct HoveredFlags: u32 {
|
||||
/// [`Ui::is_item_hovered`] only: Return true if any children of the window is hovered
|
||||
const CHILD_WINDOWS = sys::ImGuiHoveredFlags_ChildWindows;
|
||||
/// [`Ui::is_item_hovered`] only: Test from root window (top most parent of the current hierarchy)
|
||||
const ROOT_WINDOW = sys::ImGuiHoveredFlags_RootWindow;
|
||||
/// [`Ui::is_item_hovered`] only: Return true if any window is hovered
|
||||
const ANY_WINDOW = sys::ImGuiHoveredFlags_AnyWindow;
|
||||
/// [`Ui::is_item_hovered`] only: Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow)
|
||||
const NO_POPUP_HIERARCHY = sys::ImGuiHoveredFlags_NoPopupHierarchy;
|
||||
/// Return true even if a popup window is normally blocking access to this item/window
|
||||
const ALLOW_WHEN_BLOCKED_BY_POPUP = sys::ImGuiHoveredFlags_AllowWhenBlockedByPopup;
|
||||
/// Return true even if an active item is blocking access to this item
|
||||
/// Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
|
||||
const ALLOW_WHEN_BLOCKED_BY_ACTIVE_ITEM = sys::ImGuiHoveredFlags_AllowWhenBlockedByActiveItem;
|
||||
/// Return true even if the position is obstructed or overlapped by another window
|
||||
const ALLOW_WHEN_OVERLAPPED = sys::ImGuiHoveredFlags_AllowWhenOverlapped;
|
||||
/// Return true even if the item is disabled
|
||||
/// [`Ui::is_item_hovered`] only: Return true even if the item uses AllowOverlap mode and is overlapped by another hoverable item.
|
||||
const ALLOW_WHEN_OVERLAPPED_BY_ITEM = sys::ImGuiHoveredFlags_AllowWhenOverlappedByItem;
|
||||
/// [`Ui::is_item_hovered`] only: Return true even if the position is obstructed or overlapped by another window.
|
||||
const ALLOW_WHEN_OVERLAPPED_BY_WINDOW = sys::ImGuiHoveredFlags_AllowWhenOverlappedByWindow;
|
||||
/// [`Ui::is_item_hovered`] only: Return true even if the item is disabled
|
||||
const ALLOW_WHEN_DISABLED = sys::ImGuiHoveredFlags_AllowWhenDisabled;
|
||||
const RECT_ONLY = sys::ImGuiHoveredFlags_RectOnly;
|
||||
const DELAY_NORMAL = sys::ImGuiHoveredFlags_DelayNormal;
|
||||
/// [`Ui::is_item_hovered`] only: Disable using gamepad/keyboard navigation state when active, always query mouse
|
||||
const NO_NAV_OVERRIDE = sys::ImGuiHoveredFlags_NoNavOverride;
|
||||
|
||||
/// Union of [`HoveredFlags::ALLOW_WHEN_OVERLAPPED_BY_ITEM`] and [`HoveredFlags::ALLOW_WHEN_OVERLAPPED_BY_WINDOW`],
|
||||
const ALLOW_WHEN_OVERLAPPED = Self::ALLOW_WHEN_OVERLAPPED_BY_ITEM.bits | Self::ALLOW_WHEN_OVERLAPPED_BY_WINDOW.bits;
|
||||
|
||||
/// Union of [`HoveredFlags::ALLOW_WHEN_BLOCKED_BY_POPUP`], [`HoveredFlags::ALLOW_WHEN_BLOCKED_BY_ACTIVE_ITEM`],
|
||||
/// [`HoveredFlags::ALLOW_WHEN_OVERLAPPED_BY_ITEM`], and [`HoveredFlags::ALLOW_WHEN_OVERLAPPED_BY_WINDOW`],
|
||||
const RECT_ONLY = Self::ALLOW_WHEN_BLOCKED_BY_POPUP.bits | Self::ALLOW_WHEN_BLOCKED_BY_ACTIVE_ITEM.bits | Self::ALLOW_WHEN_OVERLAPPED.bits;
|
||||
|
||||
/// Union of [`HoveredFlags::ROOT_WINDOW`], [`HoveredFlags::CHILD_WINDOWS`],
|
||||
const ROOT_AND_CHILD_WINDOWS = Self::ROOT_WINDOW.bits | Self::CHILD_WINDOWS.bits;
|
||||
|
||||
/// Tooltips mode
|
||||
/// - typically used in [`Ui::is_item_hovered`] + [`Ui::tooltip`] sequence.
|
||||
/// - this is a shortcut to pull flags from [`Style::hover_flags_for_tooltip_mouse`] or
|
||||
/// [`Style::hover_flags_for_tooltip_nav`] where you can reconfigure desired behavior.
|
||||
/// - for frequently actioned or hovered items providing a tooltip, you want may to use
|
||||
/// [`HoveredFlags::FOR_TOOLTIP`] (stationary + delay) so the tooltip doesn't show too often.
|
||||
/// - for items which main purpose is to be hovered, or items with low affordance, or in less
|
||||
/// consistent apps, prefer no delay or shorter delay.
|
||||
const FOR_TOOLTIP = sys::ImGuiHoveredFlags_ForTooltip;
|
||||
/// Require mouse to be stationary for [`Style::hover_stationary_delay`] (~0.15 sec)
|
||||
/// _at least one time_. After this, can move on same item/window.
|
||||
/// Using the stationary test tends to reduces the need for a long delay.
|
||||
const STATIONARY = sys::ImGuiHoveredFlags_Stationary;
|
||||
/// [`Ui::is_item_hovered`] only: Return true immediately (default).
|
||||
/// As this is the default you generally ignore this.
|
||||
const DELAY_NONE = sys::ImGuiHoveredFlags_DelayNone;
|
||||
/// [`Ui::is_item_hovered`] only: Return true after [`Style::hover_delay_short`]
|
||||
/// elapsed (~0.15 sec) (shared between items) + requires mouse to be stationary
|
||||
/// for [`Style::hover_stationary_delay`] (once per item).
|
||||
const DELAY_SHORT = sys::ImGuiHoveredFlags_DelayShort;
|
||||
// [`Ui::is_item_hovered`] only: Return true after [`Style::hover_delay_normal`]
|
||||
// elapsed (~0.40 sec) (shared between items) + requires mouse to be stationary
|
||||
/// for [`Style::hover_stationary_delay`] (once per item).
|
||||
const DELAY_NORMAL = sys::ImGuiHoveredFlags_DelayNormal;
|
||||
/// [`Ui::is_item_hovered`] only: Disable shared delay system where moving from one item to the next keeps
|
||||
/// the previous timer for a short time (standard for tooltips with long delays)
|
||||
const NO_SHARED_DELAY = sys::ImGuiHoveredFlags_NoSharedDelay;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +91,7 @@ impl Ui {
|
||||
}
|
||||
/// Returns `true` if the last item is hovered based on the given flags
|
||||
#[doc(alias = "IsItemHovered")]
|
||||
pub fn is_item_hovered_with_flags(&self, flags: ItemHoveredFlags) -> bool {
|
||||
pub fn is_item_hovered_with_flags(&self, flags: HoveredFlags) -> bool {
|
||||
unsafe { sys::igIsItemHovered(flags.bits() as i32) }
|
||||
}
|
||||
/// Returns `true` if the last item is active
|
||||
@ -132,9 +188,9 @@ impl Ui {
|
||||
/// Allows the last item to be overlapped by a subsequent item.
|
||||
///
|
||||
/// Both may be activated during the same frame before the later one takes priority.
|
||||
#[doc(alias = "SetItemAllowOverlap")]
|
||||
#[doc(alias = "SetNextItemAllowOverlap")]
|
||||
pub fn set_item_allow_overlap(&self) {
|
||||
unsafe { sys::igSetItemAllowOverlap() };
|
||||
unsafe { sys::igSetNextItemAllowOverlap() };
|
||||
}
|
||||
/// Makes the last item the default focused item of the window
|
||||
#[doc(alias = "SetItemDefaultFocus")]
|
||||
|
||||
@ -9,15 +9,15 @@ bitflags!(
|
||||
#[repr(transparent)]
|
||||
pub struct SelectableFlags: u32 {
|
||||
/// Clicking this don't close parent popup window
|
||||
const DONT_CLOSE_POPUPS = sys::ImGuiSelectableFlags_DontClosePopups;
|
||||
const DONT_CLOSE_POPUPS = sys::ImGuiSelectableFlags_NoAutoClosePopups;
|
||||
/// Selectable frame can span all columns (text will still fit in current column)
|
||||
const SPAN_ALL_COLUMNS = sys::ImGuiSelectableFlags_SpanAllColumns;
|
||||
/// Generate press events on double clicks too
|
||||
const ALLOW_DOUBLE_CLICK = sys::ImGuiSelectableFlags_AllowDoubleClick;
|
||||
/// Cannot be selected, display greyed out text
|
||||
const DISABLED = sys::ImGuiSelectableFlags_Disabled;
|
||||
/// (WIP) Hit testing to allow subsequent willdgets to overlap this one
|
||||
const ALLOW_ITEM_OVERLAP = sys::ImGuiSelectableFlags_AllowItemOverlap;
|
||||
/// Hit testing to allow subsequent willdgets to overlap this one
|
||||
const ALLOW_OVERLAP = sys::ImGuiSelectableFlags_AllowOverlap;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -53,4 +53,22 @@ impl Ui {
|
||||
pub fn bullet_text(&self, text: impl AsRef<str>) {
|
||||
unsafe { sys::igBulletText(fmt_ptr(), self.scratch_txt(text)) }
|
||||
}
|
||||
|
||||
/// Hyperlink style text button, returns true when clicked.
|
||||
///
|
||||
/// See [`Ui::text_link_open_url`] for a way to open a hyperlink.
|
||||
#[doc(alias = "TextLink")]
|
||||
pub fn text_link(&self, text: impl AsRef<str>) -> bool {
|
||||
unsafe { sys::igTextLink(self.scratch_txt(text)) }
|
||||
}
|
||||
|
||||
/// Hyperlink style text button, opens link when clicked.
|
||||
///
|
||||
/// See [`Ui::text_link_open_url`] for a text-link which
|
||||
/// only returns true, rather than opening the link itself.
|
||||
#[doc(alias = "TextLinkOpenURL")]
|
||||
pub fn text_link_open_url(&self, label: impl AsRef<str>, url: impl AsRef<str>) {
|
||||
let (label, url) = self.scratch_txt_two(label, url);
|
||||
unsafe { sys::igTextLinkOpenURL(label, url) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ bitflags!(
|
||||
/// Full colored frame (e.g. for CollapsingHeader)
|
||||
const FRAMED = sys::ImGuiTreeNodeFlags_Framed;
|
||||
/// Hit testing to allow subsequent widgets to overlap this one
|
||||
const ALLOW_ITEM_OVERLAP = sys::ImGuiTreeNodeFlags_AllowItemOverlap;
|
||||
const ALLOW_OVERLAP = sys::ImGuiTreeNodeFlags_AllowOverlap;
|
||||
/// Don't push a tree node when open (e.g. for CollapsingHeader) = no extra indent nor
|
||||
/// pushing on ID stack
|
||||
const NO_TREE_PUSH_ON_OPEN = sys::ImGuiTreeNodeFlags_NoTreePushOnOpen;
|
||||
@ -195,7 +195,7 @@ impl<'a, T: AsRef<str>, L: AsRef<str>> TreeNode<'a, T, L> {
|
||||
///
|
||||
/// Disabled by default.
|
||||
pub fn allow_item_overlap(mut self, value: bool) -> Self {
|
||||
self.flags.set(TreeNodeFlags::ALLOW_ITEM_OVERLAP, value);
|
||||
self.flags.set(TreeNodeFlags::ALLOW_OVERLAP, value);
|
||||
self
|
||||
}
|
||||
|
||||
@ -390,7 +390,7 @@ impl<T: AsRef<str>> CollapsingHeader<T> {
|
||||
/// Disabled by default.
|
||||
#[inline]
|
||||
pub fn allow_item_overlap(mut self, value: bool) -> Self {
|
||||
self.flags.set(TreeNodeFlags::ALLOW_ITEM_OVERLAP, value);
|
||||
self.flags.set(TreeNodeFlags::ALLOW_OVERLAP, value);
|
||||
self
|
||||
}
|
||||
/// Sets the default open state for the collapsing header.
|
||||
|
||||
@ -11,12 +11,12 @@ use crate::{sys, Id};
|
||||
pub struct ChildWindow<'ui> {
|
||||
ui: &'ui Ui,
|
||||
id: u32,
|
||||
child_flags: ChildFlags,
|
||||
flags: WindowFlags,
|
||||
size: [f32; 2],
|
||||
content_size: [f32; 2],
|
||||
focused: bool,
|
||||
bg_alpha: f32,
|
||||
border: bool,
|
||||
}
|
||||
|
||||
impl<'ui> ChildWindow<'ui> {
|
||||
@ -34,12 +34,12 @@ impl<'ui> ChildWindow<'ui> {
|
||||
Self {
|
||||
ui,
|
||||
id: id.0,
|
||||
child_flags: ChildFlags::empty(),
|
||||
flags: WindowFlags::empty(),
|
||||
size: [0.0, 0.0],
|
||||
content_size: [0.0, 0.0],
|
||||
focused: false,
|
||||
bg_alpha: f32::NAN,
|
||||
border: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,11 +88,10 @@ impl<'ui> ChildWindow<'ui> {
|
||||
self
|
||||
}
|
||||
/// Enables/disables the child window border.
|
||||
///
|
||||
/// Disabled by default.
|
||||
#[deprecated(since = "0.13.0", note = "use `child_flags` instead")]
|
||||
#[inline]
|
||||
pub fn border(mut self, border: bool) -> Self {
|
||||
self.border = border;
|
||||
self.child_flags.set(ChildFlags::BORDERS, border);
|
||||
self
|
||||
}
|
||||
/// Enables/disables moving the window when child window is dragged.
|
||||
@ -199,15 +198,16 @@ impl<'ui> ChildWindow<'ui> {
|
||||
.set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
|
||||
self
|
||||
}
|
||||
/// When enabled, ensures child windows without border use `style.window_padding`.
|
||||
|
||||
/// Sets the child flags on the [`ChildWindow`].
|
||||
///
|
||||
/// Disabled by default.
|
||||
#[inline]
|
||||
pub fn always_use_window_padding(mut self, value: bool) -> Self {
|
||||
self.flags
|
||||
.set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
|
||||
/// See [`ChildFlags`] for more information on each flag.
|
||||
/// The default flags are [`ChildFlags::empty`].
|
||||
pub fn child_flags(mut self, child_flags: ChildFlags) -> Self {
|
||||
self.child_flags = child_flags;
|
||||
self
|
||||
}
|
||||
|
||||
/// Enables/disables gamepad/keyboard navigation within the window.
|
||||
///
|
||||
/// Enabled by default.
|
||||
@ -270,7 +270,7 @@ impl<'ui> ChildWindow<'ui> {
|
||||
sys::igBeginChild_ID(
|
||||
self.id,
|
||||
self.size.into(),
|
||||
self.border,
|
||||
self.child_flags.bits() as i32,
|
||||
self.flags.bits() as i32,
|
||||
)
|
||||
};
|
||||
@ -299,3 +299,39 @@ create_token!(
|
||||
/// Ends a window
|
||||
drop { sys::igEndChild() }
|
||||
);
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Configuration flags for child windows
|
||||
/// Flags for [``]
|
||||
/// About using AutoResizeX/AutoResizeY flags:
|
||||
/// - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints").
|
||||
/// - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing.
|
||||
/// - This allows BeginChild() to return false when not within boundaries (e.g. when scrolling), which is more optimal. BUT it won't update its auto-size while clipped.
|
||||
/// While not perfect, it is a better default behavior as the always-on performance gain is more valuable than the occasional "resizing after becoming visible again" glitch.
|
||||
/// - You may also use ImGuiChildFlags_AlwaysAutoResize to force an update even when child window is not in view.
|
||||
/// HOWEVER PLEASE UNDERSTAND THAT DOING SO WILL PREVENT BeginChild() FROM EVER RETURNING FALSE, disabling benefits of coarse clipping.
|
||||
#[repr(transparent)]
|
||||
pub struct ChildFlags: u32 {
|
||||
/// Show an outer border and enable WindowPadding
|
||||
const BORDERS = sys::ImGuiChildFlags_Borders;
|
||||
/// Pad with style.WindowPadding even if no border are drawn
|
||||
/// (no padding by default for non-bordered child windows because it makes more sense)
|
||||
const ALWAYS_USE_WINDOW_PADDING = sys::ImGuiChildFlags_AlwaysUseWindowPadding;
|
||||
/// Allow resize from right border (layout direction).
|
||||
const RESIZE_X = sys::ImGuiChildFlags_ResizeX;
|
||||
/// Allow resize from bottom border (layout direction).
|
||||
const RESIZE_Y = sys::ImGuiChildFlags_ResizeY;
|
||||
/// Enable auto-resizing width. Read "IMPORTANT: Size measurement" details above.
|
||||
const AUTO_RESIZE_X = sys::ImGuiChildFlags_AutoResizeX;
|
||||
/// Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above.
|
||||
const AUTO_RESIZE_Y = sys::ImGuiChildFlags_AutoResizeY;
|
||||
/// Combined with AutoResizeX/AutoResizeY.
|
||||
/// Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED.
|
||||
const ALWAYS_AUTO_RESIZE = sys::ImGuiChildFlags_AlwaysAutoResize;
|
||||
/// Style the child window like a framed item:
|
||||
/// use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.
|
||||
const FRAME_STYLE = sys::ImGuiChildFlags_FrameStyle;
|
||||
/// [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
|
||||
const NAV_FLATTENED = sys::ImGuiChildFlags_NavFlattened;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,13 +3,6 @@ use crate::Ui;
|
||||
|
||||
/// # Content region
|
||||
impl Ui {
|
||||
/// Returns the current content boundaries (in *window coordinates*)
|
||||
#[doc(alias = "GetContentRegionMax")]
|
||||
pub fn content_region_max(&self) -> [f32; 2] {
|
||||
let mut out = sys::ImVec2::zero();
|
||||
unsafe { sys::igGetContentRegionMax(&mut out) };
|
||||
out.into()
|
||||
}
|
||||
/// Equal to `ui.content_region_max()` - `ui.cursor_pos()`
|
||||
#[doc(alias = "GetContentRegionAvail")]
|
||||
pub fn content_region_avail(&self) -> [f32; 2] {
|
||||
@ -17,30 +10,4 @@ impl Ui {
|
||||
unsafe { sys::igGetContentRegionAvail(&mut out) };
|
||||
out.into()
|
||||
}
|
||||
/// Content boundaries min (in *window coordinates*).
|
||||
///
|
||||
/// Roughly equal to [0.0, 0.0] - scroll.
|
||||
#[doc(alias = "GetContentRegionMin")]
|
||||
pub fn window_content_region_min(&self) -> [f32; 2] {
|
||||
let mut out = sys::ImVec2::zero();
|
||||
unsafe { sys::igGetWindowContentRegionMin(&mut out) };
|
||||
out.into()
|
||||
}
|
||||
/// Content boundaries max (in *window coordinates*).
|
||||
///
|
||||
/// Roughly equal to [0.0, 0.0] + size - scroll.
|
||||
#[doc(alias = "GetContentRegionMax")]
|
||||
pub fn window_content_region_max(&self) -> [f32; 2] {
|
||||
let mut out = sys::ImVec2::zero();
|
||||
unsafe { sys::igGetWindowContentRegionMax(&mut out) };
|
||||
out.into()
|
||||
}
|
||||
#[doc(alias = "GetContentRegionWidth")]
|
||||
#[deprecated(
|
||||
since = "0.9.0",
|
||||
note = "Removed in Dear ImGui 1.85, 'not very useful in practice' and can be done with window_content_region_min/_max"
|
||||
)]
|
||||
pub fn window_content_region_width(&self) -> f32 {
|
||||
self.window_content_region_max()[0] - self.window_content_region_min()[0]
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,8 +84,6 @@ bitflags! {
|
||||
const ALWAYS_VERTICAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysVerticalScrollbar;
|
||||
/// Always show horizontal scrollbar
|
||||
const ALWAYS_HORIZONTAL_SCROLLBAR = sys::ImGuiWindowFlags_AlwaysHorizontalScrollbar;
|
||||
/// Ensure child windows without border use `style.window_padding`
|
||||
const ALWAYS_USE_WINDOW_PADDING = sys::ImGuiWindowFlags_AlwaysUseWindowPadding;
|
||||
/// Disable gamepad/keyboard navigation within the window
|
||||
const NO_NAV_INPUTS = sys::ImGuiWindowFlags_NoNavInputs;
|
||||
/// No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by
|
||||
@ -418,15 +416,6 @@ impl<'ui, 'a, Label: AsRef<str>> Window<'ui, 'a, Label> {
|
||||
.set(WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR, value);
|
||||
self
|
||||
}
|
||||
/// When enabled, ensures child windows without border use `style.window_padding`.
|
||||
///
|
||||
/// Disabled by default.
|
||||
#[inline]
|
||||
pub fn always_use_window_padding(mut self, value: bool) -> Self {
|
||||
self.flags
|
||||
.set(WindowFlags::ALWAYS_USE_WINDOW_PADDING, value);
|
||||
self
|
||||
}
|
||||
/// Enables/disables gamepad/keyboard navigation within the window.
|
||||
///
|
||||
/// Enabled by default.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user