diff --git a/examples/test_window.rs b/examples/test_window.rs index 28a51e8..7384c8c 100644 --- a/examples/test_window.rs +++ b/examples/test_window.rs @@ -1,12 +1,68 @@ #[macro_use] extern crate glium; +#[macro_use] extern crate imgui; extern crate time; +use imgui::Frame; + mod support; fn main() { + // let mut show_app_metrics = false; + let show_app_main_menu_bar = true; + support::main_with_frame(|frame| { - frame.show_test_window(); + // if show_app_metrics { show_metrics_window(&mut show_app_metrics) } + if show_app_main_menu_bar { show_example_app_main_menu_bar(frame) } }); } + +fn show_example_app_main_menu_bar<'a>(frame: &Frame<'a>) { + frame.main_menu_bar(|| { + frame.menu(im_str!("File")).build(|| { + show_example_menu_file(frame); + }); + frame.menu(im_str!("Edit")).build(|| { + if frame.menu_item(im_str!("Undo")).shortcut(im_str!("CTRL+Z")).build() { } + if frame.menu_item(im_str!("Redo")) + .shortcut(im_str!("CTRL+Y")).enabled(false).build() { } + frame.separator(); + if frame.menu_item(im_str!("Cut")).shortcut(im_str!("CTRL+X")).build() { } + if frame.menu_item(im_str!("Copy")).shortcut(im_str!("CTRL+C")).build() { } + if frame.menu_item(im_str!("Paste")).shortcut(im_str!("CTRL+V")).build() { } + }); + }); +} + +fn show_example_menu_file<'a>(frame: &Frame<'a>) { + frame.menu_item(im_str!("(dummy menu)")).enabled(false).build(); + if frame.menu_item(im_str!("New")).build() { } + if frame.menu_item(im_str!("Open")).shortcut(im_str!("Ctrl+O")).build() { } + frame.menu(im_str!("Open Recent")).build(|| { + frame.menu_item(im_str!("fish_hat.c")).build(); + frame.menu_item(im_str!("fish_hat.inl")).build(); + frame.menu_item(im_str!("fish_hat.h")).build(); + frame.menu(im_str!("More..")).build(|| { + frame.menu_item(im_str!("Hello")); + frame.menu_item(im_str!("Sailor")); + frame.menu(im_str!("Recurse..")).build(|| { + show_example_menu_file(frame); + }); + }); + }); + if frame.menu_item(im_str!("Save")).shortcut(im_str!("Ctrl+S")).build() { } + if frame.menu_item(im_str!("Save As..")).build() { } + frame.separator(); + frame.menu(im_str!("Options")).build(|| { + // TODO + }); + frame.menu(im_str!("Colors")).build(|| { + // TODO + }); + frame.menu(im_str!("Disabled")).enabled(false).build(|| { + unreachable!(); + }); + if frame.menu_item(im_str!("Checked")).selected(true).build() { } + if frame.menu_item(im_str!("Quit")).shortcut(im_str!("Alt+F4")).build() { } +} diff --git a/src/lib.rs b/src/lib.rs index ee0c6b9..a8dd354 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,9 +16,11 @@ use std::mem; use std::ptr; use std::slice; -pub use ffi::{ImDrawIdx, ImDrawVert, ImVec2, ImVec4}; +pub use ffi::{ImDrawIdx, ImDrawVert, ImGuiWindowFlags, ImVec2, ImVec4}; +pub use menus::{Menu, MenuItem}; pub mod ffi; +mod menus; #[cfg(feature = "glium")] pub mod glium_renderer; @@ -29,7 +31,7 @@ pub struct ImGui; macro_rules! im_str { ($e:expr) => ({ let value = concat!($e, "\0"); - unsafe { ImStr::from_bytes(value.as_bytes()) } + unsafe { ::imgui::ImStr::from_bytes(value.as_bytes()) } }); } @@ -133,17 +135,17 @@ pub struct DrawList<'a> { pub vtx_buffer: &'a [ffi::ImDrawVert] } -pub struct Frame<'a> { - _phantom: PhantomData<&'a ImGui> +pub struct Frame<'fr> { + _phantom: PhantomData<&'fr ImGui> } static FMT: &'static [u8] = b"%s\0"; fn fmt_ptr() -> *const c_char { FMT.as_ptr() as *const c_char } -impl<'a> Frame<'a> { +impl<'fr> Frame<'fr> { pub fn render(self, mut f: F) -> Result<(), E> - where F: FnMut(DrawList<'a>) -> Result<(), E> { + where F: FnMut(DrawList<'fr>) -> Result<(), E> { unsafe { let mut im_draw_data = mem::zeroed(); RENDER_DRAW_LISTS_STATE.0 = &mut im_draw_data; @@ -172,7 +174,7 @@ impl<'a> Frame<'a> { } // Widgets -impl<'a> Frame<'a> { +impl<'fr> Frame<'fr> { pub fn text<'b>(&self, text: ImStr<'b>) { // TODO: use igTextUnformatted unsafe { @@ -211,6 +213,32 @@ impl<'a> Frame<'a> { } } +// Widgets: Menus +impl<'fr> Frame<'fr> { + pub fn main_menu_bar(&self, f: F) where F: FnOnce() { + let render = unsafe { ffi::igBeginMainMenuBar() }; + if render { + f(); + unsafe { ffi::igEndMainMenuBar() }; + } + } + pub fn menu_bar(&self, f: F) where F: FnOnce() { + let render = unsafe { ffi::igBeginMenuBar() }; + if render { + f(); + unsafe { ffi::igEndMenuBar() }; + } + } + pub fn menu<'p>(&self, label: ImStr<'p>) -> Menu<'fr, 'p> { Menu::new(label) } + pub fn menu_item<'p>(&self, label: ImStr<'p>) -> MenuItem<'fr, 'p> { MenuItem::new(label) } +} + +impl<'fr> Frame<'fr> { + pub fn separator(&self) { + unsafe { ffi:: igSeparator() }; + } +} + struct RenderDrawListsState(*mut ffi::ImDrawData); unsafe impl Sync for RenderDrawListsState {} diff --git a/src/menus.rs b/src/menus.rs new file mode 100644 index 0000000..074c6ee --- /dev/null +++ b/src/menus.rs @@ -0,0 +1,81 @@ +use std::marker::PhantomData; +use std::ptr; + +use super::ffi; +use super::{Frame, ImStr}; + +pub struct Menu<'fr, 'p> { + label: ImStr<'p>, + enabled: bool, + _phantom: PhantomData<&'fr Frame<'fr>> +} + +impl<'fr, 'p> Menu<'fr, 'p> { + pub fn new(label: ImStr<'p>) -> Self { + Menu { + label: label, + enabled: true, + _phantom: PhantomData + } + } + pub fn enabled(self, enabled: bool) -> Self { + Menu { + enabled: enabled, + .. self + } + } + pub fn build(self, f: F) { + let render = unsafe { ffi::igBeginMenu(self.label.as_ptr(), self.enabled) }; + if render { + f(); + unsafe { ffi::igEndMenu() }; + } + } +} + +pub struct MenuItem<'fr, 'p> { + label: ImStr<'p>, + shortcut: Option>, + selected: bool, + enabled: bool, + _phantom: PhantomData<&'fr Frame<'fr>> +} + +impl<'fr, 'p> MenuItem<'fr, 'p> { + pub fn new(label: ImStr<'p>) -> Self { + MenuItem { + label: label, + shortcut: None, + selected: false, + enabled: true, + _phantom: PhantomData + } + } + pub fn shortcut(self, shortcut: ImStr<'p>) -> Self { + MenuItem { + shortcut: Some(shortcut), + .. self + } + } + pub fn selected(self, selected: bool) -> Self { + MenuItem { + selected: selected, + .. self + } + } + pub fn enabled(self, enabled: bool) -> Self { + MenuItem { + enabled: enabled, + .. self + } + } + pub fn build(self) -> bool { + let label = self.label.as_ptr(); + let shortcut = self.shortcut.map(|x| x.as_ptr()).unwrap_or(ptr::null()); + let selected = self.selected; + let enabled = self.enabled; + unsafe { + ffi::igMenuItem(label, shortcut, selected, enabled) + } + } +}