menu rewrite

This commit is contained in:
Jack Mac 2021-10-12 11:26:34 -04:00 committed by Jonathan Spira
parent bcc951a8fc
commit 311a31d74c
3 changed files with 107 additions and 71 deletions

View File

@ -24,6 +24,8 @@
- Added `add_polyline` method to `DrawListMut`, which binds to Dear ImGui's `AddPolyline` and `AddConvexPolyFilled`
- BREAKING: `MenuItem::new` now takes `&ui`, but has been deprecated. Instead, use `ui.menu_item`.
## [0.8.0] - 2021-09-17
Welcome to the `0.8.0` update. This is one of the largest updates imgui-rs has ever seen; it will generate errors in a `0.7` project, but hopefully it should be both quick to fix, and enjoyable to update. See our [release page](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.8.0) for more information and a list of contributors to this cycle. Thank you to everyone who uses `imgui-rs`, files issues, and spend their time and effort to PR new changes into the codebase. Because of all that effort, this is by far the best `imgui-rs` has looked!

View File

@ -336,46 +336,29 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
window.build(|| {
let _w = ui.push_item_width(-140.0);
ui.text(format!("dear imgui says hello. ({})", imgui::dear_imgui_version()));
if let Some(menu_bar) = ui.begin_menu_bar() {
if let Some(_menu_bar) = ui.begin_menu_bar() {
if let Some(menu) = ui.begin_menu("Menu") {
show_example_menu_file(ui, &mut state.file_menu);
menu.end();
}
if let Some(menu) = ui.begin_menu("Examples") {
MenuItem::new("Main menu bar")
.build_with_ref(ui, &mut state.show_app_main_menu_bar);
MenuItem::new("Console")
.build_with_ref(ui, &mut state.show_app_console);
MenuItem::new("Log")
.build_with_ref(ui, &mut state.show_app_log);
MenuItem::new("Simple layout")
.build_with_ref(ui, &mut state.show_app_layout);
MenuItem::new("Property editor")
.build_with_ref(ui, &mut state.show_app_property_editor);
MenuItem::new("Long text display")
.build_with_ref(ui, &mut state.show_app_long_text);
MenuItem::new("Auto-resizing window")
.build_with_ref(ui, &mut state.show_app_auto_resize);
MenuItem::new("Constrained-resizing window")
.build_with_ref(ui, &mut state.show_app_constrained_resize);
MenuItem::new("Simple overlay")
.build_with_ref(ui, &mut state.show_app_fixed_overlay);
MenuItem::new("Manipulating window title")
.build_with_ref(ui, &mut state.show_app_manipulating_window_title);
MenuItem::new("Custom rendering")
.build_with_ref(ui, &mut state.show_app_custom_rendering);
menu.end();
if let Some(_t) = ui.begin_menu("Examples") {
ui.menu_item_selected_ref("Main menu bar", &mut state.show_app_main_menu_bar);
ui.menu_item_selected_ref("Console", &mut state.show_app_console);
ui.menu_item_selected_ref("Log", &mut state.show_app_log);
ui.menu_item_selected_ref("Simple layout", &mut state.show_app_layout);
ui.menu_item_selected_ref("Property editor", &mut state.show_app_property_editor);
ui.menu_item_selected_ref("Long text display", &mut state.show_app_long_text);
ui.menu_item_selected_ref("Auto-resizing window", &mut state.show_app_auto_resize);
ui.menu_item_selected_ref("Constrained-resizing window", &mut state.show_app_constrained_resize);
ui.menu_item_selected_ref("Simple overlay", &mut state.show_app_fixed_overlay);
ui.menu_item_selected_ref("Manipulating window title", &mut state.show_app_manipulating_window_title);
ui.menu_item_selected_ref("Custom Rendering", &mut state.show_app_custom_rendering);
}
if let Some(menu) = ui.begin_menu("Help") {
MenuItem::new("Metrics")
.build_with_ref(ui, &mut state.show_app_metrics);
MenuItem::new("Style Editor")
.build_with_ref(ui, &mut state.show_app_style_editor);
MenuItem::new("About ImGui")
.build_with_ref(ui, &mut state.show_app_about);
menu.end();
if let Some(_menu) = ui.begin_menu("Help") {
ui.menu_item_selected_ref("Metrics", &mut state.show_app_metrics);
ui.menu_item_selected_ref("Style Editor", &mut state.show_app_style_editor);
ui.menu_item_selected_ref("About ImGui", &mut state.show_app_about);
}
menu_bar.end();
}
ui.spacing();
if CollapsingHeader::new("Help").build(ui) {
@ -843,15 +826,15 @@ fn show_example_app_main_menu_bar(ui: &Ui, state: &mut State) {
menu.end();
}
if let Some(menu) = ui.begin_menu("Edit") {
MenuItem::new("Undo").shortcut("CTRL+Z").build(ui);
MenuItem::new("Redo")
ui.menu_item_shortcut("Undo", "CTRL+Z");
ui.menu_item_config("Redo")
.shortcut("CTRL+Y")
.enabled(false)
.build(ui);
.build();
ui.separator();
MenuItem::new("Cut").shortcut("CTRL+X").build(ui);
MenuItem::new("Copy").shortcut("CTRL+C").build(ui);
MenuItem::new("Paste").shortcut("CTRL+V").build(ui);
ui.menu_item_shortcut("Cut", "CTRL+X");
ui.menu_item_shortcut("Copy", "CTRL+C");
ui.menu_item_shortcut("Paste", "CTRL+V");
menu.end();
}
menu_bar.end();
@ -859,29 +842,29 @@ fn show_example_app_main_menu_bar(ui: &Ui, state: &mut State) {
}
fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) {
MenuItem::new("(dummy menu)").enabled(false).build(ui);
MenuItem::new("New").build(ui);
MenuItem::new("Open").shortcut("Ctrl+O").build(ui);
if let Some(menu) = ui.begin_menu("Open Recent") {
MenuItem::new("fish_hat.c").build(ui);
MenuItem::new("fish_hat.inl").build(ui);
MenuItem::new("fish_hat.h").build(ui);
ui.menu_item_enabled("(dummy_menu)", false);
ui.menu_item("New");
ui.menu_item_shortcut("Open", "Ctrl+O");
if let Some(_menu) = ui.begin_menu("Open Recent") {
ui.menu_item("fish_hat.c");
ui.menu_item("fish_hat.inl");
ui.menu_item("fish_hat.h");
if let Some(menu) = ui.begin_menu("More..") {
MenuItem::new("Hello").build(ui);
MenuItem::new("Sailor").build(ui);
if let Some(menu) = ui.begin_menu("Recurse..") {
ui.menu_item("Hello");
ui.menu_item("Sailor");
if let Some(_menu) = ui.begin_menu("Recurse..") {
show_example_menu_file(ui, state);
menu.end();
}
menu.end();
}
menu.end();
}
MenuItem::new("Save").shortcut("Ctrl+S").build(ui);
MenuItem::new("Save As..").build(ui);
ui.menu_item_shortcut("Save", "Ctrl+S");
ui.menu_item("Save As..");
ui.separator();
if let Some(menu) = ui.begin_menu("Options") {
MenuItem::new("Enabled").build_with_ref(ui, &mut state.enabled);
if let Some(_menu) = ui.begin_menu("Options") {
ui.menu_item_selected_ref("Enabled", &mut state.enabled);
ui.child_window("child")
.size([0.0, 60.0])
.border(true)
@ -896,17 +879,15 @@ fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) {
let items = ["Yes", "No", "Maybe"];
ui.combo_simple_string("Combo", &mut state.n, &items);
ui.checkbox("Check", &mut state.b);
menu.end();
}
if let Some(menu) = ui.begin_menu("Colors") {
if let Some(_menu) = ui.begin_menu("Colors") {
for &col in StyleColor::VARIANTS.iter() {
MenuItem::new(format!("{:?}", col)).build(ui);
ui.menu_item(format!("{:?}", col));
}
menu.end();
}
assert!(ui.begin_menu_with_enabled("Disabled", false).is_none());
MenuItem::new("Checked").selected(true).build(ui);
MenuItem::new("Quit").shortcut("Alt+F4").build(ui);
ui.menu_item_selected("Checked", true);
ui.menu_item_shortcut("Quit", "Alt+F4");
}
fn show_example_app_auto_resize(ui: &Ui, state: &mut AutoResizeState, opened: &mut bool) {

View File

@ -107,31 +107,83 @@ impl Ui {
f();
}
}
/// Creates a menu item with the given label, returning `true` if it was pressed.
///
/// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item(&self, label: impl AsRef<str>) -> bool {
self.menu_item_config(label).build()
}
/// Creates a menu item with the given label and enablement, returning `true` if it was pressed.
///
/// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item_enabled(&self, label: impl AsRef<str>, enabled: bool) -> bool {
self.menu_item_config(label).enabled(enabled).build()
}
/// Creates a menu item with the given label and selection, returning `true` if it was pressed.
///
/// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item_selected(&self, label: impl AsRef<str>, selected: bool) -> bool {
self.menu_item_config(label).selected(selected).build()
}
/// Creates a menu item with the given label and selection, returning `true` if it was pressed,
/// while mutating `selected` to the correct state.
///
/// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item_selected_ref(&self, label: impl AsRef<str>, selected: &mut bool) -> bool {
self.menu_item_config(label).build_with_ref(selected)
}
/// Creates a menu item with the given label and shortcut, returning `true` if it was pressed.
///
/// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item_shortcut(&self, label: impl AsRef<str>, shortcut: impl AsRef<str>) -> bool {
self.menu_item_config(label).shortcut(shortcut).build()
}
// Creates a menu item builder, with further methods on it as needed.
//
// Note: a `menu_item` is the actual button/selectable within a Menu.
pub fn menu_item_config<L: AsRef<str>>(&self, label: L) -> MenuItem<'_, L> {
MenuItem {
label,
shortcut: None,
selected: false,
enabled: false,
ui: self,
}
}
}
/// Builder for a menu item.
#[derive(Copy, Clone, Debug)]
#[must_use]
pub struct MenuItem<Label, Shortcut = &'static str> {
pub struct MenuItem<'ui, Label, Shortcut = &'static str> {
label: Label,
shortcut: Option<Shortcut>,
selected: bool,
enabled: bool,
ui: &'ui Ui,
}
impl<Label: AsRef<str>> MenuItem<Label> {
impl<'ui, Label: AsRef<str>> MenuItem<'ui, Label> {
/// Construct a new menu item builder.
pub fn new(label: Label) -> Self {
#[deprecated(since = "0.9.0", note = "Use `ui.menu_item` or `ui.menu_item_config`")]
pub fn new(label: Label, ui: &'ui Ui) -> Self {
MenuItem {
label,
shortcut: None,
selected: false,
enabled: true,
ui,
}
}
}
impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
impl<'ui, Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<'ui, Label, Shortcut> {
/// Sets the menu item shortcut.
///
/// Shortcuts are displayed for convenience only and are not automatically handled.
@ -139,12 +191,13 @@ impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
pub fn shortcut<Shortcut2: AsRef<str>>(
self,
shortcut: Shortcut2,
) -> MenuItem<Label, Shortcut2> {
) -> MenuItem<'ui, Label, Shortcut2> {
MenuItem {
label: self.label,
shortcut: Some(shortcut),
selected: self.selected,
enabled: self.enabled,
ui: self.ui,
}
}
/// Sets the selected state of the menu item.
@ -167,17 +220,17 @@ impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
///
/// Returns true if the menu item is activated.
#[doc(alias = "MenuItemBool")]
pub fn build(self, ui: &Ui) -> bool {
pub fn build(self) -> bool {
unsafe {
let (label, shortcut) = ui.scratch_txt_with_opt(self.label, self.shortcut);
let (label, shortcut) = self.ui.scratch_txt_with_opt(self.label, self.shortcut);
sys::igMenuItem_Bool(label, shortcut, self.selected, self.enabled)
}
}
#[doc(alias = "MenuItemBool")]
/// Builds the menu item using a mutable reference to selected state.
pub fn build_with_ref(self, ui: &Ui, selected: &mut bool) -> bool {
if self.selected(*selected).build(ui) {
pub fn build_with_ref(self, selected: &mut bool) -> bool {
if self.selected(*selected).build() {
*selected = !*selected;
true
} else {