mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
@@ -0,0 +1,72 @@
|
||||
extern crate sdl2;
|
||||
|
||||
use sdl2::pixels::Color;
|
||||
use sdl2::event::Event;
|
||||
use sdl2::keyboard::Keycode;
|
||||
use ::sdl2::messagebox::*;
|
||||
|
||||
pub fn main() {
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let video_subsystem = sdl_context.video().unwrap();
|
||||
|
||||
let window = video_subsystem.window("rust-sdl2 demo: Video", 800, 600)
|
||||
.position_centered()
|
||||
.opengl()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut renderer = window.renderer().build().unwrap();
|
||||
|
||||
renderer.set_draw_color(Color::RGB(255, 0, 0));
|
||||
renderer.clear();
|
||||
renderer.present();
|
||||
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||
|
||||
'running: loop {
|
||||
for event in event_pump.poll_iter() {
|
||||
match event {
|
||||
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
|
||||
let res =
|
||||
show_simple_message_box(MESSAGEBOX_ERROR,
|
||||
"Some title",
|
||||
"Some information inside the window",
|
||||
renderer.window());
|
||||
match res {
|
||||
Ok(_) => {}
|
||||
Err(ShowMessageError::SdlError(string)) => {
|
||||
println!("An error occured : {}",string);
|
||||
}
|
||||
Err(_) => println!("Unexpected error occured !"),
|
||||
};
|
||||
break 'running
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// The rest of the game loop goes here...
|
||||
}
|
||||
let buttons : Vec<_> = vec![
|
||||
ButtonData {
|
||||
flags:MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
|
||||
button_id:1,
|
||||
text:"Ok"
|
||||
},
|
||||
ButtonData {
|
||||
flags:MESSAGEBOX_BUTTON_NOTHING,
|
||||
button_id:2,
|
||||
text:"No"
|
||||
},
|
||||
ButtonData {
|
||||
flags:MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
|
||||
button_id:3,
|
||||
text:"Cancel"
|
||||
},
|
||||
];
|
||||
let res = show_message_box(MESSAGEBOX_WARNING,
|
||||
buttons.as_slice(),
|
||||
"Some warning",
|
||||
"You forget to do something, do it anyway ?",
|
||||
None,
|
||||
None);
|
||||
println!("{:?}",res);
|
||||
}
|
||||
@@ -1,11 +1,77 @@
|
||||
use libc::{c_int, c_char, uint32_t};
|
||||
use std::os::raw::{c_int,c_char};
|
||||
use video::SDL_Window;
|
||||
|
||||
pub type SDL_MessageBoxFlags = u32;
|
||||
pub const SDL_MESSAGEBOX_ERROR : SDL_MessageBoxFlags = 0x00000010;
|
||||
pub const SDL_MESSAGEBOX_WARNING : SDL_MessageBoxFlags = 0x00000020;
|
||||
pub const SDL_MESSAGEBOX_INFORMATION : SDL_MessageBoxFlags = 0x00000040;
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum SDL_MessageBoxFlags {
|
||||
SDL_MESSAGEBOX_ERROR = 16,
|
||||
SDL_MESSAGEBOX_WARNING = 32,
|
||||
SDL_MESSAGEBOX_INFORMATION = 64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum SDL_MessageBoxButtonFlags {
|
||||
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 1,
|
||||
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SDL_MessageBoxButtonData {
|
||||
pub flags: u32,
|
||||
pub buttonid: c_int,
|
||||
pub text: *const c_char,
|
||||
}
|
||||
impl ::std::default::Default for SDL_MessageBoxButtonData {
|
||||
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SDL_MessageBoxColor {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum SDL_MessageBoxColorType {
|
||||
SDL_MESSAGEBOX_COLOR_BACKGROUND = 0,
|
||||
SDL_MESSAGEBOX_COLOR_TEXT = 1,
|
||||
SDL_MESSAGEBOX_COLOR_BUTTON_BORDER = 2,
|
||||
SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND = 3,
|
||||
SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED = 4,
|
||||
SDL_MESSAGEBOX_COLOR_MAX = 5,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SDL_MessageBoxColorScheme {
|
||||
pub colors: [SDL_MessageBoxColor; 5usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct SDL_MessageBoxData {
|
||||
pub flags: u32,
|
||||
pub window: *mut SDL_Window,
|
||||
pub title: *const c_char,
|
||||
pub message: *const c_char,
|
||||
pub numbuttons: c_int,
|
||||
pub buttons: *const SDL_MessageBoxButtonData,
|
||||
pub color_scheme: *const SDL_MessageBoxColorScheme,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn SDL_ShowSimpleMessageBox(flags: uint32_t, title: *const c_char, message: *const c_char, window: *mut SDL_Window) -> c_int;
|
||||
pub fn SDL_ShowMessageBox(messageboxdata: *const SDL_MessageBoxData,
|
||||
buttonid: *mut c_int)
|
||||
-> c_int;
|
||||
|
||||
pub fn SDL_ShowSimpleMessageBox(flags: u32,
|
||||
title: *const c_char,
|
||||
message: *const c_char,
|
||||
window: *mut SDL_Window)
|
||||
-> c_int;
|
||||
}
|
||||
|
||||
+140
-4
@@ -1,6 +1,6 @@
|
||||
use std::ffi::{CString, NulError};
|
||||
use std::ptr;
|
||||
use libc::c_char;
|
||||
use std::os::raw::{c_char,c_int};
|
||||
|
||||
use video::WindowRef;
|
||||
use get_error;
|
||||
@@ -9,18 +9,83 @@ use sys::messagebox as ll;
|
||||
|
||||
bitflags! {
|
||||
pub flags MessageBoxFlag: u32 {
|
||||
const MESSAGEBOX_ERROR = ::sys::messagebox::SDL_MESSAGEBOX_ERROR,
|
||||
const MESSAGEBOX_WARNING = ::sys::messagebox::SDL_MESSAGEBOX_WARNING,
|
||||
const MESSAGEBOX_INFORMATION = ::sys::messagebox::SDL_MESSAGEBOX_INFORMATION
|
||||
const MESSAGEBOX_ERROR =
|
||||
::sys::messagebox::SDL_MessageBoxFlags::SDL_MESSAGEBOX_ERROR as u32,
|
||||
const MESSAGEBOX_WARNING =
|
||||
::sys::messagebox::SDL_MessageBoxFlags::SDL_MESSAGEBOX_WARNING as u32,
|
||||
const MESSAGEBOX_INFORMATION =
|
||||
::sys::messagebox::SDL_MessageBoxFlags::SDL_MESSAGEBOX_INFORMATION as u32
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub flags MessageBoxButtonFlag: u32 {
|
||||
const MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT =
|
||||
::sys::messagebox::SDL_MessageBoxButtonFlags::SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT as u32,
|
||||
const MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT =
|
||||
::sys::messagebox::SDL_MessageBoxButtonFlags::SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT as u32,
|
||||
const MESSAGEBOX_BUTTON_NOTHING = 0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MessageBoxColorScheme {
|
||||
pub background:(u8,u8,u8),
|
||||
pub text:(u8,u8,u8),
|
||||
pub button_border:(u8,u8,u8),
|
||||
pub button_background:(u8,u8,u8),
|
||||
pub button_selected:(u8,u8,u8)
|
||||
}
|
||||
|
||||
/// button_id is the integer that will be returned
|
||||
/// by show_message_box. It is not sed by SDL2,
|
||||
/// and should only be used to know which button has been triggered
|
||||
#[derive(Debug)]
|
||||
pub struct ButtonData<'a> {
|
||||
pub flags:MessageBoxButtonFlag,
|
||||
pub button_id:i32,
|
||||
pub text:&'a str
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ClickedButton<'a> {
|
||||
CloseButton,
|
||||
CustomButton(&'a ButtonData<'a>)
|
||||
}
|
||||
|
||||
impl From<MessageBoxColorScheme> for [ll::SDL_MessageBoxColor ; 5] {
|
||||
fn from(scheme:MessageBoxColorScheme) -> [ll::SDL_MessageBoxColor ; 5] {
|
||||
fn to_message_box_color(t:(u8,u8,u8)) -> ll::SDL_MessageBoxColor {
|
||||
ll::SDL_MessageBoxColor {
|
||||
r:t.0,
|
||||
g:t.1,
|
||||
b:t.2
|
||||
}
|
||||
};
|
||||
[to_message_box_color(scheme.background),
|
||||
to_message_box_color(scheme.text),
|
||||
to_message_box_color(scheme.button_border),
|
||||
to_message_box_color(scheme.button_background),
|
||||
to_message_box_color(scheme.button_selected)]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ShowMessageError {
|
||||
InvalidTitle(NulError),
|
||||
InvalidMessage(NulError),
|
||||
/// Second argument of the tuple (i32) corresponds to the
|
||||
/// first button_id having an error
|
||||
InvalidButton(NulError,i32),
|
||||
SdlError(String),
|
||||
}
|
||||
|
||||
/// Show a simple message box, meant to be informative only.
|
||||
///
|
||||
/// There is no way to know if the user clicked "Ok" or closed the message box,
|
||||
/// If you want to retrieve which button was clicked and customize a bit more
|
||||
/// your message box, use `show_message_box` instead.
|
||||
pub fn show_simple_message_box(flags: MessageBoxFlag, title: &str,
|
||||
message: &str, window: Option<&WindowRef>)
|
||||
-> Result<(), ShowMessageError> {
|
||||
@@ -48,3 +113,74 @@ pub fn show_simple_message_box(flags: MessageBoxFlag, title: &str,
|
||||
Err(SdlError(get_error()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Show a customizable message box.
|
||||
///
|
||||
/// An array of buttons is required for it to work. The array can be empty,
|
||||
/// but it will have no button beside the close button.
|
||||
///
|
||||
/// On success, it will return either the button clicked or the close button.
|
||||
/// Note that the variant of the `ClickedButton` enum will also be returned if the message box
|
||||
/// has been forcefully closed (Alt-F4, ...)
|
||||
///
|
||||
pub fn show_message_box<'a>(flags:MessageBoxFlag, buttons:&'a [ButtonData], title:&str,
|
||||
message:&str, window:Option<&WindowRef>, scheme:Option<MessageBoxColorScheme>)
|
||||
-> Result<ClickedButton<'a>,ShowMessageError> {
|
||||
use self::ShowMessageError::*;
|
||||
let mut button_id : c_int = 0;
|
||||
let title = match CString::new(title) {
|
||||
Ok(s) => s,
|
||||
Err(err) => return Err(InvalidTitle(err)),
|
||||
};
|
||||
let message = match CString::new(message) {
|
||||
Ok(s) => s,
|
||||
Err(err) => return Err(InvalidMessage(err)),
|
||||
};
|
||||
let button_texts : Result<Vec<_>,(_,i32)> = buttons.iter().map(|b|{
|
||||
CString::new(b.text).map_err(|e|(e,b.button_id))
|
||||
}).collect(); // Create CString for every button; and catch any CString Error
|
||||
let button_texts = match button_texts {
|
||||
Ok(b) => b,
|
||||
Err(e) => return Err(InvalidButton(e.0,e.1))
|
||||
};
|
||||
let raw_buttons : Vec<ll::SDL_MessageBoxButtonData> =
|
||||
buttons.iter().zip(button_texts.iter()).map(|(b,b_text)|{
|
||||
ll::SDL_MessageBoxButtonData {
|
||||
flags:b.flags.bits(),
|
||||
buttonid:b.button_id as c_int,
|
||||
text:b_text.as_ptr()
|
||||
}
|
||||
}).collect();
|
||||
let result = unsafe {
|
||||
let msg_box_data = ll::SDL_MessageBoxData {
|
||||
flags:flags.bits(),
|
||||
window:window.map_or(ptr::null_mut(), |win| win.raw()),
|
||||
title: title.as_ptr() as *const c_char,
|
||||
message: message.as_ptr() as *const c_char,
|
||||
numbuttons: raw_buttons.len() as c_int,
|
||||
buttons: raw_buttons.as_ptr(),
|
||||
color_scheme: if let Some(scheme) = scheme {
|
||||
&ll::SDL_MessageBoxColorScheme {
|
||||
colors:From::from(scheme)
|
||||
} as *const _
|
||||
} else {
|
||||
ptr::null()
|
||||
}
|
||||
};
|
||||
ll::SDL_ShowMessageBox(
|
||||
&msg_box_data as *const _,
|
||||
&mut button_id as &mut _
|
||||
)
|
||||
} == 0;
|
||||
if result {
|
||||
match button_id {
|
||||
-1 => Ok(ClickedButton::CloseButton),
|
||||
id => {
|
||||
let button = buttons.iter().find(|b| b.button_id == id);
|
||||
Ok(ClickedButton::CustomButton(button.unwrap()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(SdlError(get_error()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user