mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-11 21:48:36 +00:00
Experiments with menus
This commit is contained in:
parent
c0c49e7bbe
commit
e261db71ba
@ -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() { }
|
||||
}
|
||||
|
||||
42
src/lib.rs
42
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<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
81
src/menus.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user