mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-27 21:38:34 +00:00
Experiments with menus
This commit is contained in:
parent
c0c49e7bbe
commit
e261db71ba
@ -1,12 +1,68 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
|
#[macro_use]
|
||||||
extern crate imgui;
|
extern crate imgui;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
|
use imgui::Frame;
|
||||||
|
|
||||||
mod support;
|
mod support;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// let mut show_app_metrics = false;
|
||||||
|
let show_app_main_menu_bar = true;
|
||||||
|
|
||||||
support::main_with_frame(|frame| {
|
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::ptr;
|
||||||
use std::slice;
|
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;
|
pub mod ffi;
|
||||||
|
mod menus;
|
||||||
|
|
||||||
#[cfg(feature = "glium")]
|
#[cfg(feature = "glium")]
|
||||||
pub mod glium_renderer;
|
pub mod glium_renderer;
|
||||||
@ -29,7 +31,7 @@ pub struct ImGui;
|
|||||||
macro_rules! im_str {
|
macro_rules! im_str {
|
||||||
($e:expr) => ({
|
($e:expr) => ({
|
||||||
let value = concat!($e, "\0");
|
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 vtx_buffer: &'a [ffi::ImDrawVert]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Frame<'a> {
|
pub struct Frame<'fr> {
|
||||||
_phantom: PhantomData<&'a ImGui>
|
_phantom: PhantomData<&'fr ImGui>
|
||||||
}
|
}
|
||||||
|
|
||||||
static FMT: &'static [u8] = b"%s\0";
|
static FMT: &'static [u8] = b"%s\0";
|
||||||
|
|
||||||
fn fmt_ptr() -> *const c_char { FMT.as_ptr() as *const c_char }
|
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>
|
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 {
|
unsafe {
|
||||||
let mut im_draw_data = mem::zeroed();
|
let mut im_draw_data = mem::zeroed();
|
||||||
RENDER_DRAW_LISTS_STATE.0 = &mut im_draw_data;
|
RENDER_DRAW_LISTS_STATE.0 = &mut im_draw_data;
|
||||||
@ -172,7 +174,7 @@ impl<'a> Frame<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Widgets
|
// Widgets
|
||||||
impl<'a> Frame<'a> {
|
impl<'fr> Frame<'fr> {
|
||||||
pub fn text<'b>(&self, text: ImStr<'b>) {
|
pub fn text<'b>(&self, text: ImStr<'b>) {
|
||||||
// TODO: use igTextUnformatted
|
// TODO: use igTextUnformatted
|
||||||
unsafe {
|
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);
|
struct RenderDrawListsState(*mut ffi::ImDrawData);
|
||||||
unsafe impl Sync for RenderDrawListsState {}
|
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