Experiments with menus

This commit is contained in:
Joonas Javanainen 2015-08-19 00:35:33 +03:00
parent c0c49e7bbe
commit e261db71ba
3 changed files with 173 additions and 8 deletions

View File

@ -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() { }
}

View File

@ -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<F, E>(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<F>(&self, f: F) where F: FnOnce() {
let render = unsafe { ffi::igBeginMainMenuBar() };
if render {
f();
unsafe { ffi::igEndMainMenuBar() };
}
}
pub fn menu_bar<F>(&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 {}

81
src/menus.rs Normal file
View File

@ -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<F: FnOnce()>(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<ImStr<'p>>,
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)
}
}
}