mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-10 04:58:34 +00:00
211 lines
8.0 KiB
Rust
211 lines
8.0 KiB
Rust
use imgui::*;
|
|
|
|
mod support;
|
|
|
|
fn main() {
|
|
let mut humans = vec![
|
|
HumanData {
|
|
name: "Joonas",
|
|
favorite_number: 102,
|
|
favorite_fruit_maybe: "Dutch",
|
|
},
|
|
HumanData {
|
|
name: "Thom",
|
|
favorite_number: 314,
|
|
favorite_fruit_maybe: "Rice",
|
|
},
|
|
HumanData {
|
|
name: "Jack",
|
|
favorite_number: 611,
|
|
favorite_fruit_maybe: "Mangoes",
|
|
},
|
|
];
|
|
|
|
let mut t2_flags = TableFlags::REORDERABLE
|
|
| TableFlags::HIDEABLE
|
|
| TableFlags::RESIZABLE
|
|
| TableFlags::NO_BORDERS_IN_BODY;
|
|
|
|
support::simple_init(file!(), move |_, ui| {
|
|
ui.window("Input text callbacks")
|
|
.size([800.0, 400.0], Condition::FirstUseEver)
|
|
.build(|| {
|
|
if let Some(_t) = ui.begin_table("Basic-Table", 3) {
|
|
// we must also call `next_row` here, because we declined
|
|
// to set up header rows. If we set up header rows ourselves,
|
|
// we will call `table_header_rows` instead, and if we use
|
|
// `begin_table_header`, then the initial call will be handled for us.
|
|
|
|
ui.table_next_row();
|
|
|
|
// note you MUST call `next_column` at least to START
|
|
// Let's walk through a table like it's an iterator...
|
|
ui.table_set_column_index(0);
|
|
ui.text("x: 0, y: 0");
|
|
|
|
ui.table_next_column();
|
|
ui.text("x: 1, y: 0");
|
|
|
|
ui.table_next_column();
|
|
ui.text("x: 2, y: 0");
|
|
|
|
// // calling next column again will wrap us around to 0-1,
|
|
// // since we've exhausted our 3 columns.
|
|
ui.table_next_column();
|
|
ui.text("x: 0, y: 1");
|
|
|
|
// // Let's do this manually now -- we can set each column ourselves...
|
|
ui.table_set_column_index(1);
|
|
ui.text("x: 1, y: 1");
|
|
|
|
ui.table_set_column_index(2);
|
|
ui.text("x: 2, y: 1");
|
|
|
|
// you CAN go back...
|
|
ui.table_set_column_index(1);
|
|
// however, you should call `new_line`, since otherwise
|
|
// we'd right on top of our `x: 1, y: 1` text.
|
|
ui.new_line();
|
|
ui.text("our of order txt");
|
|
}
|
|
|
|
ui.separator();
|
|
ui.text("Let's add some headers");
|
|
if let Some(_t) = ui.begin_table_header(
|
|
"table-headers",
|
|
[
|
|
TableColumnSetup::new("Name"),
|
|
TableColumnSetup::new("Age"),
|
|
TableColumnSetup::new("Favorite fruit"),
|
|
],
|
|
) {
|
|
// note that we DON'T have to call "table_next_row" here -- that's taken care
|
|
// of for us by `begin_table_header`, since it actually calls `table_headers_row`
|
|
|
|
// but we DO need to call column!
|
|
// but that's fine, we'll use a loop
|
|
for i in 0..3 {
|
|
let names = ["Joonas", "Thom", "Jack"];
|
|
let fruit = ["Dutch", "Rice", "Mangoes"];
|
|
|
|
ui.table_next_column();
|
|
ui.text(names[i]);
|
|
|
|
ui.table_next_column();
|
|
ui.text((i * 9).to_string());
|
|
|
|
ui.table_next_column();
|
|
ui.text(fruit[i]);
|
|
}
|
|
}
|
|
|
|
ui.separator();
|
|
ui.text("Let's do some context menus");
|
|
ui.text(
|
|
"context menus are created, by default, from the flags passed\
|
|
while making the table, or each row.\n\
|
|
Notice how toggling these checkboxes changes the context menu.",
|
|
);
|
|
|
|
ui.checkbox_flags("Reorderable", &mut t2_flags, TableFlags::REORDERABLE);
|
|
ui.same_line();
|
|
ui.checkbox_flags("Hideable", &mut t2_flags, TableFlags::HIDEABLE);
|
|
ui.same_line();
|
|
ui.checkbox_flags("Resizable", &mut t2_flags, TableFlags::RESIZABLE);
|
|
|
|
if let Some(_t) = ui.begin_table_header_with_flags(
|
|
"table-headers2",
|
|
[
|
|
TableColumnSetup::new("Name"),
|
|
TableColumnSetup::new("Age"),
|
|
TableColumnSetup::new("Favorite fruit"),
|
|
],
|
|
t2_flags,
|
|
) {
|
|
// note that we DON'T have to call "table_next_row" here -- that's taken care
|
|
// of for us by `begin_table_header`, since it actually calls `table_headers_row`
|
|
|
|
// but we DO need to call column!
|
|
// but that's fine, we'll use a loop
|
|
for i in 0..3 {
|
|
let names = ["Joonas", "Thom", "Jack"];
|
|
let fruit = ["Dutch", "Rice", "Mangoes"];
|
|
|
|
ui.table_next_column();
|
|
ui.text(names[i]);
|
|
|
|
ui.table_next_column();
|
|
ui.text((i * 9).to_string());
|
|
|
|
ui.table_next_column();
|
|
ui.text(fruit[i]);
|
|
}
|
|
}
|
|
|
|
ui.separator();
|
|
|
|
ui.text("Here's a table you can sort!");
|
|
ui.text("Check the code to see the two methods of doing it.");
|
|
|
|
if let Some(_t) = ui.begin_table_header_with_flags(
|
|
"table-headers3",
|
|
[
|
|
TableColumnSetup::new("Name"),
|
|
TableColumnSetup::new("Favorite Number"),
|
|
TableColumnSetup::new("Favorite fruit"),
|
|
],
|
|
TableFlags::SORTABLE,
|
|
) {
|
|
if let Some(sort_data) = ui.table_sort_specs_mut() {
|
|
sort_data
|
|
.conditional_sort(|specs| HumanData::sort_humans(&mut humans, specs));
|
|
|
|
// Can also sort this other way...
|
|
// if sort_data.should_sort() {
|
|
// HumanData::sort_humans(&mut humans, sort_data.specs());
|
|
// sort_data.set_sorted();
|
|
// }
|
|
}
|
|
|
|
for human in humans.iter() {
|
|
ui.table_next_column();
|
|
ui.text(human.name);
|
|
|
|
ui.table_next_column();
|
|
ui.text(human.favorite_number.to_string());
|
|
|
|
ui.table_next_column();
|
|
ui.text(human.favorite_fruit_maybe);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
struct HumanData {
|
|
name: &'static str,
|
|
favorite_number: usize,
|
|
favorite_fruit_maybe: &'static str,
|
|
}
|
|
|
|
impl HumanData {
|
|
pub fn sort_humans(humans: &mut [Self], specs: Specs<'_>) {
|
|
let spec = specs.iter().next().unwrap();
|
|
if let Some(kind) = spec.sort_direction() {
|
|
match kind {
|
|
TableSortDirection::Ascending => match spec.column_idx() {
|
|
0 => humans.sort_by_key(|h| h.name),
|
|
1 => humans.sort_by_key(|h| h.favorite_number),
|
|
2 => humans.sort_by_key(|h| h.favorite_fruit_maybe),
|
|
_ => unimplemented!(),
|
|
},
|
|
TableSortDirection::Descending => match spec.column_idx() {
|
|
0 => humans.sort_by_key(|h| std::cmp::Reverse(h.name)),
|
|
1 => humans.sort_by_key(|h| std::cmp::Reverse(h.favorite_number)),
|
|
2 => humans.sort_by_key(|h| std::cmp::Reverse(h.favorite_fruit_maybe)),
|
|
_ => unimplemented!(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|