mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-29 03:46:35 +11:00
804 lines
21 KiB
Rust
804 lines
21 KiB
Rust
//! minifb is a cross platform library written in [Rust](https://www.rust-lang.org) that makes to
|
|
//! open windows (usually native to the running operating system) and can optionally show a 32-bit
|
|
//! buffer. minifb also support keyboard, mouse input and menus on selected operating systems.
|
|
//!
|
|
use std::os::raw;
|
|
|
|
/// Scale will scale the frame buffer and the window that is being sent in when calling the update
|
|
/// function. This is useful if you for example want to display a 320 x 256 window on a screen with
|
|
/// much higher resolution which would result in that the window is very small.
|
|
#[derive(Clone, Copy)]
|
|
pub enum Scale {
|
|
/// This mode checks your current screen resolution and will caluclate the largest window size
|
|
/// that can be used within that limit and resize it. Useful if you have a small buffer to
|
|
/// display on a high resolution screen.
|
|
FitScreen,
|
|
/// 1X scale (which means leave the corrdinates sent into Window::new untouched)
|
|
X1,
|
|
/// 2X window scale (Example: 320 x 200 -> 640 x 400)
|
|
X2,
|
|
/// 4X window scale (Example: 320 x 200 -> 1280 x 800)
|
|
X4,
|
|
/// 8X window scale (Example: 320 x 200 -> 2560 x 1600)
|
|
X8,
|
|
/// 16X window scale (Example: 320 x 200 -> 5120 x 3200)
|
|
X16,
|
|
/// 32 window scale (Example: 320 x 200 -> 10240 x 6400)
|
|
X32,
|
|
}
|
|
|
|
/// Used for is_key_pressed and get_keys_pressed() to indicated if repeat of presses is wanted
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
pub enum KeyRepeat {
|
|
/// Use repeat
|
|
Yes,
|
|
/// Don't use repeat
|
|
No,
|
|
}
|
|
|
|
/// The various mouse buttons that are availible
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
pub enum MouseButton
|
|
{
|
|
/// Left mouse button
|
|
Left,
|
|
/// Middle mouse button
|
|
Middle,
|
|
/// Right mouse button
|
|
Right,
|
|
}
|
|
|
|
|
|
/// The diffrent modes that can be used to decide how mouse coordinates should be handled
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
pub enum MouseMode {
|
|
/// Return mouse coords from outside of the window (may be negative)
|
|
Pass,
|
|
/// Clamp the mouse coordinates within the window
|
|
Clamp,
|
|
/// Discared if the mouse is outside the window
|
|
Discard,
|
|
}
|
|
|
|
/// Different style of cursors that can be used
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
pub enum CursorStyle {
|
|
/// Regular arrow style (this is what the cursor normal looks like)
|
|
Arrow,
|
|
/// Used when indicating insertion (like text field)
|
|
Ibeam,
|
|
/// Cross-hair cursor
|
|
Crosshair,
|
|
/// Closed hand which useful for dragging things, may use default hand on unsupported OSes.
|
|
ClosedHand,
|
|
/// Open hand which useful for indicating drangable things, may use default hand on unsupported OSes.
|
|
OpenHand,
|
|
/// Rezining left-rigth direction
|
|
ResizeLeftRight,
|
|
/// Rezining up-down direction
|
|
ResizeUpDown,
|
|
/// Resize in all directions
|
|
ResizeAll,
|
|
}
|
|
|
|
/// This trait can be implemented and set with ```set_input_callback``` to reieve a callback
|
|
/// whene there is inputs incoming. Currently only support unicode chars.
|
|
pub trait InputCallback {
|
|
fn add_char(&mut self, uni_char: u32);
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
mod error;
|
|
pub use self::error::Error;
|
|
#[doc(hidden)]
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
#[doc(hidden)]
|
|
pub mod key;
|
|
#[doc(hidden)]
|
|
pub use key::Key as Key;
|
|
#[doc(hidden)]
|
|
pub mod os;
|
|
mod mouse_handler;
|
|
mod buffer_helper;
|
|
mod key_handler;
|
|
mod window_flags;
|
|
//mod menu;
|
|
//pub use menu::Menu as Menu;
|
|
//pub use menu::MENU_KEY_COMMAND;
|
|
//pub use menu::MENU_KEY_WIN;
|
|
//pub use menu::MENU_KEY_SHIFT;
|
|
//pub use menu::MENU_KEY_CTRL;
|
|
//pub use menu::MENU_KEY_ALT;
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
|
use self::os::macos as imp;
|
|
#[cfg(target_os = "windows")]
|
|
use self::os::windows as imp;
|
|
#[cfg(any(target_os="linux",
|
|
target_os="freebsd",
|
|
target_os="dragonfly",
|
|
target_os="netbsd",
|
|
target_os="openbsd"))]
|
|
use self::os::unix as imp;
|
|
#[cfg(target_os = "redox")]
|
|
use self::os::redox as imp;
|
|
///
|
|
/// Window is used to open up a window. It's possible to optionally display a 32-bit buffer when
|
|
/// the widow is set as non-resizable.
|
|
///
|
|
pub struct Window(imp::Window);
|
|
|
|
///
|
|
/// WindowOptions is creation settings for the window. By default the settings are defined for
|
|
/// displayng a 32-bit buffer (no scaling of window is possible)
|
|
///
|
|
pub struct WindowOptions {
|
|
/// If the window should be borderless (default: false)
|
|
pub borderless: bool,
|
|
/// If the window should have a title (default: true)
|
|
pub title: bool,
|
|
/// If it should be possible to resize the window (default: false)
|
|
pub resize: bool,
|
|
/// Scale of the window that used in conjunction with update_with_buffer (default: X1)
|
|
pub scale: Scale
|
|
}
|
|
|
|
impl Window {
|
|
///
|
|
/// Opens up a new window
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// Open up a window with default settings
|
|
///
|
|
/// ```ignore
|
|
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()) {
|
|
/// Ok(win) => win,
|
|
/// Err(err) => {
|
|
/// println!("Unable to create window {}", err);
|
|
/// return;
|
|
/// }
|
|
///};
|
|
/// ```
|
|
///
|
|
/// Open up a window that is resizeable
|
|
///
|
|
/// ```ignore
|
|
/// let mut window = match Window::new("Test", 640, 400,
|
|
/// WindowOptions {
|
|
/// resize: true,
|
|
/// ..WindowOptions::default()
|
|
/// }) {
|
|
/// Ok(win) => win,
|
|
/// Err(err) => {
|
|
/// println!("Unable to create window {}", err);
|
|
/// return;
|
|
/// }
|
|
///};
|
|
/// ```
|
|
pub fn new(name: &str, width: usize, height: usize, opts: WindowOptions) -> Result<Window> {
|
|
imp::Window::new(name, width, height, opts).map(Window)
|
|
}
|
|
|
|
///
|
|
/// Allows you to set a new title of the window after creation
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
|
|
///
|
|
/// window.set_title("My New Title!");
|
|
/// ```
|
|
///
|
|
pub fn set_title(&mut self, title: &str) {
|
|
self.0.set_title(title)
|
|
}
|
|
|
|
///
|
|
/// Returns the native handle for a window which is an opaque pointer/handle which
|
|
/// dependens on the current operating system:
|
|
///
|
|
/// ```ignore
|
|
/// Windows HWND
|
|
/// MacOS NSWindow
|
|
/// X11 XWindow
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn get_window_handle(&self) -> *mut raw::c_void {
|
|
self.0.get_window_handle()
|
|
}
|
|
|
|
///
|
|
/// Updates the window with a 32-bit pixel buffer. Notice that the buffer needs to be at least
|
|
/// the size of the created window
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let mut buffer: Vec<u32> = vec![0; 640 * 400];
|
|
///
|
|
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
|
|
///
|
|
/// window.update_with_buffer(&buffer).unwrap();
|
|
/// ```
|
|
#[inline]
|
|
pub fn update_with_buffer(&mut self, buffer: &[u32]) -> Result<()> {
|
|
self.0.update_with_buffer(buffer)
|
|
}
|
|
|
|
///
|
|
/// Updates the window (this is required to call in order to get keyboard/mouse input, etc)
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let mut buffer: Vec<u32> = vec![0; 640 * 400];
|
|
///
|
|
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
|
|
///
|
|
/// window.update();
|
|
/// ```
|
|
#[inline]
|
|
pub fn update(&mut self) {
|
|
self.0.update()
|
|
}
|
|
|
|
///
|
|
/// Checks if the window is still open. A window can be closed by the user (by for example
|
|
/// pressing the close button on the window) It's up to the user to make sure that this is
|
|
/// being checked and take action depending on the state.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// while window.is_open() {
|
|
/// window.update(...)
|
|
/// }
|
|
/// ```
|
|
#[inline]
|
|
pub fn is_open(&self) -> bool {
|
|
self.0.is_open()
|
|
}
|
|
|
|
///
|
|
/// Sets the position of the window. This is useful if you have
|
|
/// more than one window and want to align them up on the screen
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// // Moves the window to pixel position 20, 20 on the screen
|
|
/// window.set_position(20, 20);
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn set_position(&mut self, x: isize, y: isize) {
|
|
self.0.set_position(x, y)
|
|
}
|
|
|
|
///
|
|
/// Returns the current size of the window
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let size = window.get_size();
|
|
/// println!("width {} height {}", size.0, size.1);
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn get_size(&self) -> (usize, usize) {
|
|
self.0.get_size()
|
|
}
|
|
|
|
///
|
|
/// Get the current position of the mouse relative to the current window
|
|
/// The coordinate system is as 0, 0 as the upper left corner
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.get_mouse_pos(MouseMode::Clamp).map(|mouse| {
|
|
/// println!("x {} y {}", mouse.0, mouse.1);
|
|
/// });
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn get_mouse_pos(&self, mode: MouseMode) -> Option<(f32, f32)> {
|
|
self.0.get_mouse_pos(mode)
|
|
}
|
|
|
|
///
|
|
/// Get the current position of the mouse relative to the current window
|
|
/// The coordinate system is as 0, 0 as the upper left corner and ignores
|
|
/// any scaling set to the window.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.get_unscaled_mouse_pos(MouseMode::Clamp).map(|mouse| {
|
|
/// println!("x {} y {}", mouse.0, mouse.1);
|
|
/// });
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn get_unscaled_mouse_pos(&self, mode: MouseMode) -> Option<(f32, f32)> {
|
|
self.0.get_unscaled_mouse_pos(mode)
|
|
}
|
|
|
|
///
|
|
/// Check if a mouse button is down or not
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// let left_down = window.get_mouse_down(MouseButton::Left);
|
|
/// println!("is left down? {}", left_down)
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn get_mouse_down(&self, button: MouseButton) -> bool {
|
|
self.0.get_mouse_down(button)
|
|
}
|
|
|
|
///
|
|
/// Get the current movement of the scroll wheel.
|
|
/// Scroll wheel can mean different thing depending on the device attach.
|
|
/// For example on Mac with trackpad "scroll wheel" means two finger
|
|
/// swiping up/down (y axis) and to the sides (x-axis)
|
|
/// When using a mouse this assumes the scroll wheel which often is only y direction.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.get_scroll_wheel().map(|scroll| {
|
|
/// println!("scrolling - x {} y {}", scroll.0, scroll.1);
|
|
/// });
|
|
/// ```
|
|
///
|
|
///
|
|
#[inline]
|
|
pub fn get_scroll_wheel(&self) -> Option<(f32, f32)> {
|
|
self.0.get_scroll_wheel()
|
|
}
|
|
|
|
///
|
|
/// Set a different cursor style. This can be used if you have resizing
|
|
/// elements or something like that
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.set_cursor_style(CursorStyle::ResizeLeftRight);
|
|
/// ```
|
|
///
|
|
pub fn set_cursor_style(&mut self, cursor: CursorStyle) {
|
|
self.0.set_cursor_style(cursor)
|
|
}
|
|
|
|
///
|
|
/// Get the current keys that are down.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.get_keys().map(|keys| {
|
|
/// for t in keys {
|
|
/// match t {
|
|
/// Key::W => println!("holding w"),
|
|
/// Key::T => println!("holding t"),
|
|
/// _ => (),
|
|
/// }
|
|
/// }
|
|
/// });
|
|
/// ```
|
|
#[inline]
|
|
pub fn get_keys(&self) -> Option<Vec<Key>> {
|
|
self.0.get_keys()
|
|
}
|
|
|
|
///
|
|
/// Get the current pressed keys. Repeat can be used to control if keys should
|
|
/// be repeated if down or not.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.get_keys_pressed(KeyRepeat::No).map(|keys| {
|
|
/// for t in keys {
|
|
/// match t {
|
|
/// Key::W => println!("pressed w"),
|
|
/// Key::T => println!("pressed t"),
|
|
/// _ => (),
|
|
/// }
|
|
/// }
|
|
/// });
|
|
/// ```
|
|
#[inline]
|
|
pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> {
|
|
self.0.get_keys_pressed(repeat)
|
|
}
|
|
|
|
///
|
|
/// Check if a single key is down.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// if window.is_key_down(Key::A) {
|
|
/// println!("Key A is down");
|
|
/// }
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn is_key_down(&self, key: Key) -> bool {
|
|
self.0.is_key_down(key)
|
|
}
|
|
|
|
///
|
|
/// Check if a single key is pressed. KeyRepeat will control if the key should be repeated or
|
|
/// not while being pressed.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// if window.is_key_pressed(KeyRepeat::No) {
|
|
/// println!("Key A is down");
|
|
/// }
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn is_key_pressed(&self, key: Key, repeat: KeyRepeat) -> bool {
|
|
self.0.is_key_pressed(key, repeat)
|
|
}
|
|
|
|
///
|
|
/// Sets the delay for when a key is being held before it starts being repeated the default
|
|
/// value is 0.25 sec
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.set_key_repeat_delay(0.5) // 0.5 sec before repeat starts
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn set_key_repeat_delay(&mut self, delay: f32) {
|
|
self.0.set_key_repeat_delay(delay)
|
|
}
|
|
|
|
///
|
|
/// Sets the rate in between when the keys has passed the initial repeat_delay. The default
|
|
/// value is 0.05 sec
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// window.set_key_repeat_rate(0.01) // 0.01 sec between keys
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn set_key_repeat_rate(&mut self, rate: f32) {
|
|
self.0.set_key_repeat_rate(rate)
|
|
}
|
|
|
|
///
|
|
/// Returns if this windows is the current active one
|
|
///
|
|
#[inline]
|
|
pub fn is_active(&mut self) -> bool {
|
|
self.0.is_active()
|
|
}
|
|
|
|
///
|
|
/// Set input callback to recive callback on char input
|
|
///
|
|
#[inline]
|
|
pub fn set_input_callback(&mut self, callback: Box<InputCallback>) {
|
|
self.0.set_input_callback(callback)
|
|
}
|
|
|
|
///
|
|
/// This allows adding menus to your windows. As menus behaves a bit diffrently depending on
|
|
/// Operating system here is how it works.
|
|
///
|
|
/// ```ignore
|
|
/// Windows:
|
|
/// Each window has their own menu and shortcuts are active depending on active window.
|
|
/// Mac:
|
|
/// As Mac uses one menu for the whole program the menu will change depending
|
|
/// on which window you have active.
|
|
/// Linux/BSD/etc:
|
|
/// Menus aren't supported as they depend on each WindowManager and is outside of the
|
|
/// scope for this library to support. Use [get_unix_menus] to get a structure
|
|
/// ```
|
|
///
|
|
#[inline]
|
|
pub fn add_menu(&mut self, menu: &Menu) -> MenuHandle {
|
|
self.0.add_menu(&menu.0)
|
|
}
|
|
|
|
///
|
|
/// Remove a menu that has been added with [#add_menu]
|
|
///
|
|
#[inline]
|
|
pub fn remove_menu(&mut self, handle: MenuHandle) {
|
|
self.0.remove_menu(handle)
|
|
}
|
|
|
|
///
|
|
/// Get Unix menu. Will only return menus on Unix class OSes
|
|
/// otherwise ```None```
|
|
///
|
|
#[cfg(any(target_os="macos",
|
|
target_os="windows"))]
|
|
pub fn get_unix_menus(&self) -> Option<&Vec<UnixMenu>> {
|
|
None
|
|
}
|
|
|
|
#[cfg(any(target_os="linux",
|
|
target_os="freebsd",
|
|
target_os="dragonfly",
|
|
target_os="netbsd",
|
|
target_os="openbsd",
|
|
target_os="redox"))]
|
|
pub fn get_unix_menus(&self) -> Option<&Vec<UnixMenu>> {
|
|
self.0.get_unix_menus()
|
|
}
|
|
|
|
///
|
|
/// Check if a menu item has been pressed
|
|
///
|
|
#[inline]
|
|
pub fn is_menu_pressed(&mut self) -> Option<usize> {
|
|
self.0.is_menu_pressed()
|
|
}
|
|
}
|
|
|
|
|
|
/// Command key on Mac OS
|
|
pub const MENU_KEY_COMMAND: usize = 1;
|
|
/// Windows key on Windows
|
|
pub const MENU_KEY_WIN: usize = 2;
|
|
/// Shift key
|
|
pub const MENU_KEY_SHIFT: usize = 4;
|
|
/// Control key
|
|
pub const MENU_KEY_CTRL: usize = 8;
|
|
/// Alt key
|
|
pub const MENU_KEY_ALT: usize = 16;
|
|
|
|
const MENU_ID_SEPARATOR:usize = 0xffffffff;
|
|
|
|
///
|
|
/// Used on Unix (Linux, FreeBSD, etc) as menus aren't supported in a native where there.
|
|
/// This structure can be used by calling [#get_unix_menus] on Window.
|
|
///
|
|
#[derive(Debug, Clone)]
|
|
pub struct UnixMenu {
|
|
/// Name of the menu
|
|
pub name: String,
|
|
/// All items of the menu.
|
|
pub items: Vec<UnixMenuItem>,
|
|
#[doc(hidden)]
|
|
pub handle: MenuHandle,
|
|
#[doc(hidden)]
|
|
pub item_counter: MenuItemHandle,
|
|
}
|
|
|
|
///
|
|
/// Used for on Unix (Linux, FreeBSD, etc) as menus aren't supported in a native where there.
|
|
/// This structure holds info for each item in a #UnixMenu
|
|
///
|
|
#[derive(Debug, Clone)]
|
|
pub struct UnixMenuItem {
|
|
/// Set to a menu if there is a Item is a sub_menu otherwise None
|
|
pub sub_menu: Option<Box<UnixMenu>>,
|
|
/// Handle of the MenuItem
|
|
pub handle: MenuItemHandle,
|
|
/// Id of the item (set by the user from the outside and should be reported back when pressed)
|
|
pub id: usize,
|
|
/// Name of the item
|
|
pub label: String,
|
|
/// Set to true if enabled otherwise false
|
|
pub enabled: bool,
|
|
/// Shortcut key
|
|
pub key: Key,
|
|
/// Modifier for the key (Shift, Ctrl, etc)
|
|
pub modifier: usize,
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
#[doc(hidden)]
|
|
pub struct MenuItemHandle(pub u64);
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
#[doc(hidden)]
|
|
pub struct MenuHandle(pub u64);
|
|
|
|
|
|
///
|
|
/// Menu holds info for menus
|
|
///
|
|
pub struct Menu(imp::Menu);
|
|
|
|
impl Menu {
|
|
/// Create a new menu. Returns error if failed
|
|
pub fn new(name: &str) -> Result<Menu> {
|
|
imp::Menu::new(name).map(Menu)
|
|
}
|
|
|
|
#[inline]
|
|
/// Destroys a menu. Currently not implemented
|
|
pub fn destroy_menu(&mut self) {
|
|
//self.0.destroy_menu()
|
|
}
|
|
|
|
#[inline]
|
|
/// Adds a sub menu to the current menu
|
|
pub fn add_sub_menu(&mut self, name: &str, menu: &Menu) {
|
|
self.0.add_sub_menu(name, &menu.0)
|
|
}
|
|
|
|
/// Adds a menu separator
|
|
pub fn add_separator(&mut self) {
|
|
self.add_menu_item(&MenuItem { id: MENU_ID_SEPARATOR, ..MenuItem::default() });
|
|
}
|
|
|
|
#[inline]
|
|
/// Adds an item to the menu
|
|
pub fn add_menu_item(&mut self, item: &MenuItem) -> MenuItemHandle {
|
|
self.0.add_menu_item(item)
|
|
}
|
|
|
|
#[inline]
|
|
/// Adds an item to the menu. Notice that you need to call "build" to finish the add
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// menu.add_item("test", 1).shortcut(Key::A, 0).build()
|
|
/// ```
|
|
pub fn add_item(&mut self, name: &str, id: usize) -> MenuItem {
|
|
MenuItem {
|
|
id: id,
|
|
label: name.to_owned(),
|
|
menu: Some(self),
|
|
..MenuItem::default()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
/// Removes an item from the menu
|
|
pub fn remove_item(&mut self, item: &MenuItemHandle) {
|
|
self.0.remove_item(item)
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Holds info about each item in a menu
|
|
///
|
|
pub struct MenuItem<'a> {
|
|
pub id: usize,
|
|
pub label: String,
|
|
pub enabled: bool,
|
|
pub key: Key,
|
|
pub modifier: usize,
|
|
#[doc(hidden)]
|
|
pub menu: Option<&'a mut Menu>,
|
|
}
|
|
|
|
impl<'a> Default for MenuItem<'a> {
|
|
fn default() -> Self {
|
|
MenuItem {
|
|
id: MENU_ID_SEPARATOR,
|
|
label: "".to_owned(),
|
|
enabled: true,
|
|
key: Key::Unknown,
|
|
modifier: 0,
|
|
menu: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Clone for MenuItem<'a> {
|
|
fn clone(&self) -> Self {
|
|
MenuItem {
|
|
id: self.id,
|
|
label: self.label.clone(),
|
|
enabled: self.enabled,
|
|
key: self.key,
|
|
modifier: self.modifier,
|
|
menu: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> MenuItem<'a> {
|
|
/// Creates a new menu item
|
|
pub fn new(name: &str, id: usize) -> MenuItem {
|
|
MenuItem {
|
|
id: id,
|
|
label: name.to_owned(),
|
|
..MenuItem::default()
|
|
}
|
|
}
|
|
#[inline]
|
|
/// Sets a shortcut key and modifer (and returns itself)
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// menu.add_item("test", 1).shortcut(Key::A, 0).build()
|
|
/// ```
|
|
pub fn shortcut(self, key: Key, modifier: usize) -> Self {
|
|
MenuItem {
|
|
key: key,
|
|
modifier: modifier,
|
|
.. self
|
|
}
|
|
}
|
|
#[inline]
|
|
/// Sets item to a separator
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// menu.add_item("", 0).separator().build()
|
|
/// ```
|
|
/// Notice that it's usually easier to just call ```menu.add_separator()``` directly
|
|
pub fn separator(self) -> Self {
|
|
MenuItem {
|
|
id: MENU_ID_SEPARATOR,
|
|
.. self
|
|
}
|
|
}
|
|
#[inline]
|
|
/// Sets the menu item disabled/or not
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// menu.add_item("test", 1).enabled(false).build()
|
|
/// ```
|
|
pub fn enabled(self, enabled: bool) -> Self {
|
|
MenuItem {
|
|
enabled: enabled,
|
|
.. self
|
|
}
|
|
}
|
|
#[inline]
|
|
/// Must be called to finalize building of a menu item when started with ```menu.add_item()```
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```ignore
|
|
/// menu.add_item("test", 1).enabled(false).build()
|
|
/// ```
|
|
pub fn build(&mut self) -> MenuItemHandle {
|
|
let t = self.clone();
|
|
if let Some(ref mut menu) = self.menu {
|
|
menu.0.add_menu_item(&t)
|
|
} else {
|
|
MenuItemHandle(0)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Impl for WindowOptions
|
|
|
|
#[doc(hidden)]
|
|
impl Default for WindowOptions {
|
|
fn default() -> WindowOptions {
|
|
WindowOptions {
|
|
borderless: false,
|
|
title: true,
|
|
resize: false,
|
|
scale: Scale::X1,
|
|
}
|
|
}
|
|
}
|
|
|
|
|