Add ListClipper wrapper

This commit is contained in:
henbr 2020-12-31 14:38:12 +01:00 committed by Thom Chiovoloni
parent 65bfc1469e
commit 936e63bdfa
3 changed files with 143 additions and 0 deletions

View File

@ -49,6 +49,7 @@ struct State {
dont_ask_me_next_time: bool,
stacked_modals_item: usize,
stacked_modals_color: [f32; 4],
app_log: Vec<String>,
tabs: TabState,
}
@ -108,6 +109,7 @@ impl Default for State {
dont_ask_me_next_time: false,
stacked_modals_item: 0,
stacked_modals_color: [0.4, 0.7, 0.0, 0.5],
app_log: Vec::new(),
tabs: TabState::default(),
}
}
@ -312,6 +314,10 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
);
}
if state.show_app_log {
show_app_log(ui, &mut state.app_log);
}
let mut window = Window::new(im_str!("ImGui Demo"))
.title_bar(!state.no_titlebar)
.resizable(!state.no_resize)
@ -1232,3 +1238,56 @@ fn show_example_app_custom_rendering(ui: &Ui, state: &mut CustomRenderingState,
}
});
}
fn show_app_log(ui: &Ui, app_log: &mut Vec<String>) {
Window::new(im_str!("Example: Log"))
.size([500.0, 400.0], Condition::FirstUseEver)
.build(ui, || {
if ui.small_button(im_str!("[Debug] Add 5 entries")) {
let categories = ["info", "warn", "error"];
let words = [
"Bumfuzzled",
"Cattywampus",
"Snickersnee",
"Abibliophobia",
"Absquatulate",
"Nincompoop",
"Pauciloquent",
];
for _ in 0..5 {
let category = categories[app_log.len() % categories.len()];
let word = words[app_log.len() % words.len()];
let frame = ui.frame_count();
let time = ui.time();
let text = format!(
"{:05} {} Hello, current time is {:.1}, here's a word: {}",
frame, category, time, word
);
app_log.push(text);
}
}
if ui.button(im_str!("Clear"), [0.0, 0.0]) {
app_log.clear();
}
ui.same_line(0.0);
if ui.button(im_str!("Copy"), [0.0, 0.0]) {
ui.set_clipboard_text(&ImString::from(app_log.join("\n")));
}
ui.separator();
ChildWindow::new("logwindow")
.flags(WindowFlags::HORIZONTAL_SCROLLBAR)
.build(ui, || {
let mut clipper = ListClipper::new()
.items_count(app_log.len() as i32)
.begin(ui);
while clipper.step() {
for line in clipper.display_start()..clipper.display_end() {
ui.text(&app_log[line as usize]);
}
}
if ui.scroll_y() >= ui.scroll_max_y() {
ui.set_scroll_here_y();
}
});
});
}

View File

@ -23,6 +23,7 @@ pub use self::input_widget::{
pub use self::io::*;
pub use self::layout::*;
pub use self::legacy::*;
pub use self::list_clipper::ListClipper;
pub use self::plothistogram::PlotHistogram;
pub use self::plotlines::PlotLines;
pub use self::popup_modal::PopupModal;
@ -58,6 +59,7 @@ pub mod internal;
mod io;
mod layout;
mod legacy;
mod list_clipper;
mod plothistogram;
mod plotlines;
mod popup_modal;

82
imgui/src/list_clipper.rs Normal file
View File

@ -0,0 +1,82 @@
use std::marker::PhantomData;
use std::thread;
use crate::sys;
use crate::Ui;
pub struct ListClipper {
items_count: i32,
items_height: f32,
}
impl ListClipper {
pub fn new() -> Self {
ListClipper {
items_count: -1,
items_height: -1.0,
}
}
pub fn items_count(mut self, items_count: i32) -> Self {
self.items_count = items_count;
self
}
pub fn items_height(mut self, items_height: f32) -> Self {
self.items_height = items_height;
self
}
pub fn begin<'ui>(self, ui: &Ui<'ui>) -> ListClipperToken<'ui> {
let list_clipper = unsafe {
let list_clipper = sys::ImGuiListClipper_ImGuiListClipper();
sys::ImGuiListClipper_Begin(list_clipper, self.items_count, self.items_height);
list_clipper
};
ListClipperToken::new(ui, list_clipper)
}
}
pub struct ListClipperToken<'ui> {
list_clipper: *mut sys::ImGuiListClipper,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui> ListClipperToken<'ui> {
fn new(_: &Ui<'ui>, list_clipper: *mut sys::ImGuiListClipper) -> Self {
Self {
list_clipper,
_phantom: PhantomData,
}
}
pub fn step(&mut self) -> bool {
unsafe { sys::ImGuiListClipper_Step(self.list_clipper) }
}
pub fn end(&mut self) {
unsafe {
sys::ImGuiListClipper_End(self.list_clipper);
}
}
pub fn display_start(&self) -> i32 {
unsafe { (*self.list_clipper).DisplayStart }
}
pub fn display_end(&self) -> i32 {
unsafe { (*self.list_clipper).DisplayEnd }
}
}
impl<'ui> Drop for ListClipperToken<'ui> {
fn drop(&mut self) {
if !self.step() {
unsafe {
sys::ImGuiListClipper_destroy(self.list_clipper);
};
} else if !thread::panicking() {
panic!("step() was not called until it returned false");
}
}
}