webview 0.1.1

Tiny cross-platform UI library for Rust that uses a webview for rendering HTML5
Documentation
extern crate urlencoding;

mod ffi;

use ffi::*;
use std::ffi::NulError;
use std::os::raw::c_void;
use std::fmt::Display;
use urlencoding::encode;

pub enum Content<S: Into<String> + Display> {
    Url(S),
    Html(S),
}

pub struct WebView {
    window: Box<Window>,
}

impl WebView {
    pub fn new<S: Into<String>, SD: Into<String> + Display>(
        title: S,
        content: Content<SD>,
        width: i32,
        height: i32,
        resizable: bool,
        debug: bool,
    ) -> Result<Self, NulError> {
        let url = {
            match content {
                Content::Url(url) => url.into(),
                Content::Html(html) => format!("data:text/html,{}", encode(&html.into())),
            }
        };

        let priv_size = unsafe { get_priv_size() };

        let window = Box::new(Window {
            url: to_cstring_ptr(url)?,
            title: to_cstring_ptr(title)?,
            width: width,
            height: height,
            resizable: resizable as i32,
            debug: debug as i32,
            private: vec![0; priv_size],
        });

        unsafe {
            r_webview_init(&window);
        }

        Ok(WebView { window: window })
    }

    pub fn dispatch<T: Fn(&WebView) -> () + 'static>(&self, cb: T) {
        let window = &self.window;
        let boxed_self = Box::new(self);

        let data = Box::new(DispatchUserData {
            callback: Box::new(cb),
            view: Box::into_raw(boxed_self),
        });

        let raw = Box::into_raw(data);

        unsafe {
            r_webview_dispatch(window, dispatcher, raw as *mut c_void);
        }
    }

    pub fn set_title<S: Into<String>>(&self, title: S) -> Result<(), NulError> {
        let window = &self.window;
        let title = to_cstring_ptr(title.into())?;

        unsafe {
            r_webview_set_title(window, title);
        }

        Ok(())
    }

    pub fn eval<S: Into<String>>(&self, js: S) -> Result<(), NulError> {
        let window = &self.window;
        let js = to_cstring_ptr(js.into())?;

        unsafe {
            r_webview_eval(window, js);
        }

        Ok(())
    }

    pub fn inject_css<S: Into<String>>(&self, css: S) -> Result<(), NulError> {
        let window = &self.window;
        let css = to_cstring_ptr(css.into())?;

        unsafe {
            r_webview_inject_css(window, css);
        }

        Ok(())
    }

    pub fn join(&self) {
        let window = &self.window;

        unsafe { while r_webview_loop(window, 1) == 0 {} }
    }

    pub fn exit(&self) {
        let window = &self.window;

        unsafe {
            r_webview_terminate(window);
        }
    }

    pub fn loop_once(&self, blocking: bool) -> bool {
        let window = &self.window;

        unsafe { r_webview_loop(window, blocking as i32) == 0 }
    }
}

impl Drop for WebView {
    fn drop(&mut self) {
        let window = &self.window;

        unsafe {
            r_webview_exit(window);
        }
    }
}