mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-24 20:08:31 +00:00
tons of updates, added examples
This commit is contained in:
parent
805f5e93e7
commit
a0d3cbb7e4
@ -11,8 +11,7 @@ fn main() {
|
|||||||
let mut uncaptured_counter = 0u32;
|
let mut uncaptured_counter = 0u32;
|
||||||
let mut home_counter = 0u32;
|
let mut home_counter = 0u32;
|
||||||
let mut f1_release_count = 0u32;
|
let mut f1_release_count = 0u32;
|
||||||
let mut text_buffer = ImString::new("with some buffer");
|
let mut text_buffer = ImString::new("");
|
||||||
text_buffer.reserve(100);
|
|
||||||
|
|
||||||
system.main_loop(move |_, ui| {
|
system.main_loop(move |_, ui| {
|
||||||
Window::new(im_str!("Means of accessing key state"))
|
Window::new(im_str!("Means of accessing key state"))
|
||||||
|
|||||||
151
imgui-examples/examples/text_callbacks.rs
Normal file
151
imgui-examples/examples/text_callbacks.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
use imgui::*;
|
||||||
|
|
||||||
|
mod support;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let system = support::init(file!());
|
||||||
|
let mut buffers = vec![
|
||||||
|
ImString::default(),
|
||||||
|
ImString::default(),
|
||||||
|
ImString::default(),
|
||||||
|
];
|
||||||
|
|
||||||
|
system.main_loop(move |_, ui| {
|
||||||
|
Window::new(im_str!("Input text callbacks"))
|
||||||
|
.size([500.0, 300.0], Condition::FirstUseEver)
|
||||||
|
.build(ui, || {
|
||||||
|
ui.text("You can make a variety of buffer callbacks on an Input Text");
|
||||||
|
ui.text(
|
||||||
|
"or on an InputTextMultiline. In this example, we'll use \
|
||||||
|
InputText primarily.",
|
||||||
|
);
|
||||||
|
ui.text(
|
||||||
|
"The only difference is that InputTextMultiline doesn't get \
|
||||||
|
the `History` callback,",
|
||||||
|
);
|
||||||
|
ui.text("since, of course, you need the up/down keys to navigate.");
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.text("No callbacks:");
|
||||||
|
ui.input_text(im_str!("buf0"), &mut buffers[0]).build();
|
||||||
|
ui.input_text(im_str!("buf0"), &mut buffers[1]).build();
|
||||||
|
ui.input_text(im_str!("buf0"), &mut buffers[2]).build();
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.text("Here's a callback which printlns when each is ran.");
|
||||||
|
|
||||||
|
struct AllCallback;
|
||||||
|
impl InputTextCallbackHandler for AllCallback {
|
||||||
|
fn char_filter(&mut self, c: char) -> Option<char> {
|
||||||
|
println!("Char filter fired! This means a char was inputted.");
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
fn on_completion(&mut self, _: TextCallbackData<'_>) {
|
||||||
|
println!("Completion request fired! This means the tab key was hit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_edit(&mut self, _: TextCallbackData<'_>) {
|
||||||
|
println!("Edit was fired! Any edit will cause this to fire.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_history(&mut self, dir: HistoryDirection, _: TextCallbackData<'_>) {
|
||||||
|
println!("History was fired by pressing {:?}", dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_always(&mut self, _: TextCallbackData<'_>) {
|
||||||
|
// We don't actually print this out because it will flood your log a lot!
|
||||||
|
// println!("The always callback fired! It always fires.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.input_text(
|
||||||
|
im_str!("All Callbacks logging"),
|
||||||
|
buffers.get_mut(0).unwrap(),
|
||||||
|
)
|
||||||
|
.callback(InputTextCallback::all(), AllCallback)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.text("You can also define a callback on structs with data.");
|
||||||
|
ui.text("Here we implement the callback handler on a wrapper around &mut ImString");
|
||||||
|
ui.text("to duplicate edits to buf0 on buf1");
|
||||||
|
|
||||||
|
struct Wrapper<'a>(&'a mut ImString);
|
||||||
|
impl<'a> InputTextCallbackHandler for Wrapper<'a> {
|
||||||
|
fn on_always(&mut self, data: TextCallbackData<'_>) {
|
||||||
|
*self.0 = im_str!("{}", data.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (buf0, brwchk_dance) = buffers.split_first_mut().unwrap();
|
||||||
|
let buf1 = Wrapper(&mut brwchk_dance[0]);
|
||||||
|
|
||||||
|
ui.input_text(im_str!("Edits copied to buf1"), buf0)
|
||||||
|
.callback(InputTextCallback::ALWAYS, buf1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.text("Finally, we'll do some whacky history to show inserting and removing");
|
||||||
|
ui.text("characters from the buffer.");
|
||||||
|
ui.text(
|
||||||
|
"Here, pressing UP (while editing the below widget) will remove the\n\
|
||||||
|
first and last character from buf2",
|
||||||
|
);
|
||||||
|
ui.text("and pressing DOWN will prepend the first char from buf0 AND");
|
||||||
|
ui.text("append the last char from buf1");
|
||||||
|
|
||||||
|
let (buf0, brwchk_dance) = buffers.split_first_mut().unwrap();
|
||||||
|
let (buf1, buf2_dance) = brwchk_dance.split_first_mut().unwrap();
|
||||||
|
let buf2 = &mut buf2_dance[0];
|
||||||
|
|
||||||
|
struct Wrapper2<'a>(&'a str, &'a str);
|
||||||
|
|
||||||
|
impl<'a> InputTextCallbackHandler for Wrapper2<'a> {
|
||||||
|
fn on_history(
|
||||||
|
&mut self,
|
||||||
|
dir: HistoryDirection,
|
||||||
|
mut data: TextCallbackData<'_>,
|
||||||
|
) {
|
||||||
|
match dir {
|
||||||
|
HistoryDirection::Up => {
|
||||||
|
// remove first char...
|
||||||
|
if !data.str().is_empty() {
|
||||||
|
data.remove_chars(0, 1);
|
||||||
|
|
||||||
|
if let Some((idx, _)) = data.str().char_indices().rev().next() {
|
||||||
|
data.remove_chars(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HistoryDirection::Down => {
|
||||||
|
// insert first char...
|
||||||
|
if let Some(first_char) = self.0.get(0..1) {
|
||||||
|
data.insert_chars(0, first_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert last char
|
||||||
|
if let Some((idx, _)) = self.1.char_indices().rev().next() {
|
||||||
|
data.push_str(&self.1[idx..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.input_text(im_str!("Wild buf2 editor"), buf2)
|
||||||
|
.callback(
|
||||||
|
InputTextCallback::HISTORY,
|
||||||
|
Wrapper2(buf0.to_str(), buf1.to_str()),
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ui.text(
|
||||||
|
"For more examples on how to use callbacks non-chaotically, check the demo",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -183,7 +183,7 @@ impl<'ui, 'p> InputText<'ui, 'p, PassthroughCallback> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, T: TextCallbackHandler> InputText<'ui, 'p, T> {
|
impl<'ui, 'p, T: InputTextCallbackHandler> InputText<'ui, 'p, T> {
|
||||||
/// Sets the hint displayed in the input text background.
|
/// Sets the hint displayed in the input text background.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hint(mut self, hint: &'p ImStr) -> Self {
|
pub fn hint(mut self, hint: &'p ImStr) -> Self {
|
||||||
@ -194,7 +194,7 @@ impl<'ui, 'p, T: TextCallbackHandler> InputText<'ui, 'p, T> {
|
|||||||
impl_text_flags!(InputText);
|
impl_text_flags!(InputText);
|
||||||
|
|
||||||
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
|
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
|
||||||
/// for `InputText` and `InputTextMultiline`.
|
/// for [InputText] and [InputTextMultiline].
|
||||||
///
|
///
|
||||||
/// If, for some reason, you don't want this, you can run this function to prevent this.
|
/// If, for some reason, you don't want this, you can run this function to prevent this.
|
||||||
/// In that case, edits which would cause a resize will not occur.
|
/// In that case, edits which would cause a resize will not occur.
|
||||||
@ -205,7 +205,11 @@ impl<'ui, 'p, T: TextCallbackHandler> InputText<'ui, 'p, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn callback(mut self, callbacks: InputTextCallback, callback: T) -> InputText<'ui, 'p, T> {
|
pub fn callback<T2: InputTextCallbackHandler>(
|
||||||
|
mut self,
|
||||||
|
callbacks: InputTextCallback,
|
||||||
|
callback: T2,
|
||||||
|
) -> InputText<'ui, 'p, T2> {
|
||||||
if callbacks.contains(InputTextCallback::COMPLETION) {
|
if callbacks.contains(InputTextCallback::COMPLETION) {
|
||||||
self.flags.insert(InputTextFlags::CALLBACK_COMPLETION);
|
self.flags.insert(InputTextFlags::CALLBACK_COMPLETION);
|
||||||
}
|
}
|
||||||
@ -221,8 +225,14 @@ impl<'ui, 'p, T: TextCallbackHandler> InputText<'ui, 'p, T> {
|
|||||||
if callbacks.contains(InputTextCallback::EDIT) {
|
if callbacks.contains(InputTextCallback::EDIT) {
|
||||||
self.flags.insert(InputTextFlags::CALLBACK_EDIT);
|
self.flags.insert(InputTextFlags::CALLBACK_EDIT);
|
||||||
}
|
}
|
||||||
self.callback_handler = callback;
|
InputText {
|
||||||
self
|
callback_handler: callback,
|
||||||
|
label: self.label,
|
||||||
|
hint: self.hint,
|
||||||
|
buf: self.buf,
|
||||||
|
flags: self.flags,
|
||||||
|
_phantom: self._phantom,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> bool {
|
pub fn build(self) -> bool {
|
||||||
@ -285,11 +295,11 @@ impl<'ui, 'p> InputTextMultiline<'ui, 'p, PassthroughCallback> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ui, 'p, T: TextCallbackHandler> InputTextMultiline<'ui, 'p, T> {
|
impl<'ui, 'p, T: InputTextCallbackHandler> InputTextMultiline<'ui, 'p, T> {
|
||||||
impl_text_flags!(InputText);
|
impl_text_flags!(InputText);
|
||||||
|
|
||||||
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
|
/// By default (as of 0.8.0), imgui-rs will automatically handle string resizes
|
||||||
/// for `InputText` and `InputTextMultiline`.
|
/// for [InputText] and [InputTextMultiline].
|
||||||
///
|
///
|
||||||
/// If, for some reason, you don't want this, you can run this function to prevent this.
|
/// If, for some reason, you don't want this, you can run this function to prevent this.
|
||||||
/// In that case, edits which would cause a resize will not occur.
|
/// In that case, edits which would cause a resize will not occur.
|
||||||
@ -544,7 +554,7 @@ bitflags!(
|
|||||||
///
|
///
|
||||||
/// Each method here lists the flag required to call it, and this module begins
|
/// Each method here lists the flag required to call it, and this module begins
|
||||||
/// with an example of callbacks being used.
|
/// with an example of callbacks being used.
|
||||||
pub trait TextCallbackHandler {
|
pub trait InputTextCallbackHandler {
|
||||||
/// Filters a char -- returning a `None` means that the char is removed,
|
/// Filters a char -- returning a `None` means that the char is removed,
|
||||||
/// and returning another char substitutes it out.
|
/// and returning another char substitutes it out.
|
||||||
///
|
///
|
||||||
@ -743,15 +753,14 @@ impl<'a> TextCallbackData<'a> {
|
|||||||
/// at some byte pos.
|
/// at some byte pos.
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// Panics if the `pos` is not a char boundary or if
|
/// Panics if the `pos` is not a char boundary.
|
||||||
/// there are not enough chars remaining.
|
|
||||||
pub fn remove_chars(&mut self, pos: usize, char_count: usize) {
|
pub fn remove_chars(&mut self, pos: usize, char_count: usize) {
|
||||||
let inner = &self.str()[pos..];
|
let inner = &self.str()[pos..];
|
||||||
let byte_count = inner
|
let byte_count = inner
|
||||||
.char_indices()
|
.char_indices()
|
||||||
.nth(char_count)
|
.nth(char_count)
|
||||||
.expect("not enough characters in string")
|
.map(|v| v.0)
|
||||||
.0;
|
.unwrap_or(inner.len());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.remove_chars_unchecked(pos, byte_count);
|
self.remove_chars_unchecked(pos, byte_count);
|
||||||
@ -798,7 +807,7 @@ struct UserData<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This is our default callback.
|
/// This is our default callback.
|
||||||
extern "C" fn callback<T: TextCallbackHandler>(
|
extern "C" fn callback<T: InputTextCallbackHandler>(
|
||||||
data: *mut sys::ImGuiInputTextCallbackData,
|
data: *mut sys::ImGuiInputTextCallbackData,
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
struct CallbackData<'a, T> {
|
struct CallbackData<'a, T> {
|
||||||
@ -885,4 +894,4 @@ extern "C" fn callback<T: TextCallbackHandler>(
|
|||||||
/// If you do not set a callback handler, this will be used (but will never
|
/// If you do not set a callback handler, this will be used (but will never
|
||||||
/// actually run, since you will not have pass imgui any flags).
|
/// actually run, since you will not have pass imgui any flags).
|
||||||
pub struct PassthroughCallback;
|
pub struct PassthroughCallback;
|
||||||
impl TextCallbackHandler for PassthroughCallback {}
|
impl InputTextCallbackHandler for PassthroughCallback {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user