use conrod::{Dimensions, Ui, UiBuilder};
use conrod::backend;
use conrod::image::Map as ImageMap;
use conrod::text::GlyphCache;
use conrod::text::rt::Rect;
use graphics::Viewport;
use handlers::render::conrod::provider::ConrodProvider;
use handlers::store::Store;
use opengles_graphics::{GlGraphics, Texture};
use slog;
use std::ops::{Deref, DerefMut};
use texture::{Format, TextureSettings, UpdateTexture};
use wlc::render::RenderOutput;
pub struct ConrodInstance {
pub ui: Ui,
pub text_tex: Texture,
pub text_cache: GlyphCache,
pub image_map: ImageMap<Texture>,
provider: Vec<Box<ConrodProvider>>,
logger: slog::Logger,
}
impl ConrodInstance {
pub fn new(dim: Dimensions, logger: slog::Logger) -> ConrodInstance {
let len = (dim[0] * dim[1] * 4.0) as usize;
let mut empty: Vec<u8> = Vec::with_capacity(len);
for _ in 0..len {
empty.push(0u8);
}
ConrodInstance {
ui: UiBuilder::new(dim).build(),
text_tex: Texture::from_memory_alpha(&empty,
dim[0] as u32,
dim[1] as u32,
&TextureSettings::new())
.unwrap(),
text_cache: GlyphCache::new(dim[0] as u32, dim[1] as u32, 0.1, 0.1),
image_map: ImageMap::new(),
provider: Vec::new(),
logger: logger,
}
}
pub fn register<P: ConrodProvider + 'static>(&mut self, provider: P) {
self.provider.push(Box::new(provider));
}
pub fn image_map(&mut self) -> &mut ImageMap<Texture> {
&mut self.image_map
}
pub fn render(&mut self, output: &mut RenderOutput) {
trace!(self.logger, "Updating Widgets");
{
let mut cell = self.ui.set_widgets();
for child in &mut self.provider {
child.render(output, &mut cell);
}
}
trace!(self.logger, "Rendering");
let res = output.resolution();
if let Some(gl) = output.get::<GlGraphics>() {
fn texture_from_image<T>(img: &T) -> &T {
img
};
fn cache_queued_glyphs(_: &mut GlGraphics, tex: &mut Texture, rect: Rect<u32>, data: &[u8]) {
struct Bytes {
b: u8,
i: u8,
}
impl Iterator for Bytes {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
let b = match self.i {
0 | 1 | 2 => 255,
3 => self.b,
_ => return None,
};
self.i += 1;
Some(b)
}
}
UpdateTexture::update(tex,
&mut (),
Format::Rgba8,
&data.iter().flat_map(|x| Bytes { b: *x, i: 0 }).collect::<Vec<u8>>(),
[rect.min.x, rect.min.y],
[rect.width(), rect.height()])
.unwrap()
}
let primitives = self.ui.draw();
let text_tex = &mut self.text_tex;
let text_cache = &mut self.text_cache;
let map = &self.image_map;
gl.write().unwrap().draw(Viewport {
rect: [0, 0, res.w as i32, res.h as i32],
draw_size: [res.w, res.h],
window_size: [res.w, res.h],
},
move |c, g| {
backend::piston::draw::primitives(primitives,
c,
g,
text_tex,
text_cache,
map,
cache_queued_glyphs,
texture_from_image);
});
}
}
}
impl Deref for ConrodInstance {
type Target = Ui;
fn deref(&self) -> &Ui {
&self.ui
}
}
impl DerefMut for ConrodInstance {
fn deref_mut(&mut self) -> &mut Ui {
&mut self.ui
}
}