From 6e184ad4d513b33ef593606559a24fcb9c272d5e Mon Sep 17 00:00:00 2001 From: orhanbalci Date: Sat, 28 May 2016 14:37:38 +0300 Subject: [PATCH] formatting fixed, unnecessary functions removed --- src/glium_renderer.rs.bk | 209 +++++++++++++++++++++++++++++++++++++++ src/input.rs.bk | 163 ++++++++++++++++++++++++++++++ src/lib.rs | 34 ++++--- src/menus.rs.bk | 87 ++++++++++++++++ src/sliders.rs.bk | 91 +++++++++++++++++ src/trees.rs.bk | 56 +++++++++++ src/widgets.rs.bk | 57 +++++++++++ src/window.rs.bk | 200 +++++++++++++++++++++++++++++++++++++ 8 files changed, 886 insertions(+), 11 deletions(-) create mode 100644 src/glium_renderer.rs.bk create mode 100644 src/input.rs.bk create mode 100644 src/menus.rs.bk create mode 100644 src/sliders.rs.bk create mode 100644 src/trees.rs.bk create mode 100644 src/widgets.rs.bk create mode 100644 src/window.rs.bk diff --git a/src/glium_renderer.rs.bk b/src/glium_renderer.rs.bk new file mode 100644 index 0000000..2338b7d --- /dev/null +++ b/src/glium_renderer.rs.bk @@ -0,0 +1,209 @@ +use glium::{ + index, program, texture, vertex, + Blend, DrawError, DrawParameters, GlObject, IndexBuffer, Program, Rect, Surface, Texture2d, + VertexBuffer +}; +use glium::backend::{Context, Facade}; +use glium::index::PrimitiveType; +use glium::texture::{ClientFormat, RawImage2d}; +use libc::uintptr_t; +use std::borrow::Cow; +use std::fmt; +use std::rc::Rc; + +use super::{DrawList, Ui, ImDrawIdx, ImDrawVert, ImGui}; + +pub type RendererResult = Result; + +#[derive(Clone, Debug)] +pub enum RendererError { + Vertex(vertex::BufferCreationError), + Index(index::BufferCreationError), + Program(program::ProgramChooserCreationError), + Texture(texture::TextureCreationError), + Draw(DrawError) +} + +impl fmt::Display for RendererError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::RendererError::*; + match *self { + Vertex(_) => write!(f, "Vertex buffer creation failed"), + Index(_) => write!(f, "Index buffer creation failed"), + Program(ref e) => write!(f, "Program creation failed: {}", e), + Texture(_) => write!(f, "Texture creation failed"), + Draw(ref e) => write!(f, "Drawing failed: {}", e) + } + } +} + +impl From for RendererError { + fn from(e: vertex::BufferCreationError) -> RendererError { + RendererError::Vertex(e) + } +} + +impl From for RendererError { + fn from(e: index::BufferCreationError) -> RendererError { + RendererError::Index(e) + } +} + +impl From for RendererError { + fn from(e: program::ProgramChooserCreationError) -> RendererError { + RendererError::Program(e) + } +} + +impl From for RendererError { + fn from(e: texture::TextureCreationError) -> RendererError { + RendererError::Texture(e) + } +} + +impl From for RendererError { + fn from(e: DrawError) -> RendererError { + RendererError::Draw(e) + } +} + +pub struct Renderer { + ctx: Rc, + device_objects: DeviceObjects +} + +impl Renderer { + pub fn init(imgui: &mut ImGui, ctx: &F) -> RendererResult { + let device_objects = try!(DeviceObjects::init(imgui, ctx)); + Ok(Renderer { + ctx: ctx.get_context().clone(), + device_objects: device_objects + }) + } + pub fn render<'a, S: Surface>(&mut self, surface: &mut S, + ui: Ui<'a>) -> RendererResult<()> { + let _ = self.ctx.insert_debug_marker("imgui-rs: starting rendering"); + let result = ui.render(|draw_list| self.render_draw_list(surface, draw_list)); + let _ = self.ctx.insert_debug_marker("imgui-rs: rendering finished"); + result + } + fn render_draw_list<'a, S: Surface>(&mut self, surface: &mut S, + draw_list: DrawList<'a>) -> RendererResult<()> { + try!(self.device_objects.upload_vertex_buffer(&self.ctx, draw_list.vtx_buffer)); + try!(self.device_objects.upload_index_buffer(&self.ctx, draw_list.idx_buffer)); + + let (width, height) = surface.get_dimensions(); + let matrix = [ + [ 2.0 / (width as f32), 0.0, 0.0, 0.0 ], + [ 0.0, 2.0 / -(height as f32), 0.0, 0.0 ], + [ 0.0, 0.0, -1.0, 0.0 ], + [ -1.0, 1.0, 0.0, 1.0 ] + ]; + let font_texture_id = self.device_objects.texture.get_id() as uintptr_t; + + let mut idx_start = 0; + for cmd in draw_list.cmd_buffer { + // We don't support custom textures...yet! + assert!(cmd.texture_id as uintptr_t == font_texture_id); + let uniforms = uniform! { + matrix: matrix, + tex: &self.device_objects.texture + }; + let draw_params = DrawParameters { + blend: Blend::alpha_blending(), + scissor: Some(Rect { + left: cmd.clip_rect.x as u32, + bottom: (height as f32 - cmd.clip_rect.w) as u32, + width: (cmd.clip_rect.z - cmd.clip_rect.x) as u32, + height: (cmd.clip_rect.w - cmd.clip_rect.y) as u32 + }), + .. Default::default() + }; + let idx_end = idx_start + cmd.elem_count as usize; + try!(surface.draw(&self.device_objects.vertex_buffer, + &self.device_objects.index_buffer.slice(idx_start ..idx_end) + .expect("Invalid index buffer range"), + &self.device_objects.program, + &uniforms, + &draw_params)); + idx_start = idx_end; + } + Ok(()) + } +} + +pub struct DeviceObjects { + vertex_buffer: VertexBuffer, + index_buffer: IndexBuffer, + program: Program, + texture: Texture2d +} + +fn compile_default_program(ctx: &F) -> Result { + program!( + ctx, + 140 => { + vertex: include_str!("shader/vert_140.glsl"), + fragment: include_str!("shader/frag_140.glsl"), + outputs_srgb: true + }, + 110 => { + vertex: include_str!("shader/vert_110.glsl"), + fragment: include_str!("shader/frag_110.glsl"), + outputs_srgb: true + } + ) +} + +impl DeviceObjects { + pub fn init(im_gui: &mut ImGui, ctx: &F) -> RendererResult { + let vertex_buffer = try!(VertexBuffer::empty_dynamic(ctx, 0)); + let index_buffer = try!(IndexBuffer::empty_dynamic(ctx, PrimitiveType::TrianglesList, 0)); + + let program = try!(compile_default_program(ctx)); + let texture = try!(im_gui.prepare_texture(|handle| { + let data = RawImage2d { + data: Cow::Borrowed(handle.pixels), + width: handle.width, + height: handle.height, + format: ClientFormat::U8U8U8U8 + }; + Texture2d::new(ctx, data) + })); + im_gui.set_texture_id(texture.get_id() as uintptr_t); + + Ok(DeviceObjects { + vertex_buffer: vertex_buffer, + index_buffer: index_buffer, + program: program, + texture: texture + }) + } + pub fn upload_vertex_buffer(&mut self, ctx: &F, + vtx_buffer: &[ImDrawVert]) -> RendererResult<()> { + self.vertex_buffer.invalidate(); + if let Some(slice) = self.vertex_buffer.slice_mut(0 .. vtx_buffer.len()) { + slice.write(vtx_buffer); + return Ok(()); + } + self.vertex_buffer = try!(VertexBuffer::dynamic(ctx, vtx_buffer)); + let _ = ctx.get_context().insert_debug_marker( + &format!("imgui-rs: resized vertex buffer to {} bytes", + self.vertex_buffer.get_size())); + Ok(()) + } + pub fn upload_index_buffer(&mut self, ctx: &F, + idx_buffer: &[ImDrawIdx]) -> RendererResult<()> { + self.index_buffer.invalidate(); + if let Some(slice) = self.index_buffer.slice_mut(0 .. idx_buffer.len()) { + slice.write(idx_buffer); + return Ok(()); + } + self.index_buffer = + try!(IndexBuffer::dynamic(ctx, PrimitiveType::TrianglesList, idx_buffer)); + let _ = ctx.get_context().insert_debug_marker( + &format!("imgui-rs: resized index buffer to {} bytes", + self.index_buffer.get_size())); + Ok(()) + } +} diff --git a/src/input.rs.bk b/src/input.rs.bk new file mode 100644 index 0000000..3948e54 --- /dev/null +++ b/src/input.rs.bk @@ -0,0 +1,163 @@ +use imgui_sys; +use libc::size_t; +use std::marker::PhantomData; +use std::ptr; + +use super::{ + Ui, + ImGuiInputTextFlags, ImGuiInputTextFlags_CharsDecimal, ImGuiInputTextFlags_CharsHexadecimal, + ImGuiInputTextFlags_CharsUppercase, ImGuiInputTextFlags_CharsNoBlank, + ImGuiInputTextFlags_AutoSelectAll, ImGuiInputTextFlags_EnterReturnsTrue, + ImGuiInputTextFlags_CallbackCompletion, ImGuiInputTextFlags_CallbackHistory, + ImGuiInputTextFlags_CallbackAlways, ImGuiInputTextFlags_CallbackCharFilter, + ImGuiInputTextFlags_AllowTabInput, //ImGuiInputTextFlags_CtrlEnterForNewLine, + ImGuiInputTextFlags_NoHorizontalScroll, ImGuiInputTextFlags_AlwaysInsertMode, + ImStr +}; + +#[must_use] +pub struct InputText<'ui, 'p> { + label: ImStr<'p>, + buf: &'p mut str, + flags: ImGuiInputTextFlags, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> InputText<'ui, 'p> { + pub fn new(label: ImStr<'p>, buf: &'p mut str) -> Self { + InputText { + label: label, + buf: buf, + flags: ImGuiInputTextFlags::empty(), + _phantom: PhantomData + } + } + + #[inline] + pub fn flags(self, flags: ImGuiInputTextFlags) -> Self { + InputText { + flags: flags, + .. self + } + } + + #[inline] + pub fn chars_decimal(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CharsDecimal, value), + .. self + } + } + + #[inline] + pub fn chars_hexadecimal(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CharsHexadecimal, value), + .. self + } + } + + #[inline] + pub fn chars_uppercase(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CharsUppercase, value), + .. self + } + } + + #[inline] + pub fn chars_noblank(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CharsNoBlank, value), + .. self + } + } + + #[inline] + pub fn auto_select_all(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_AutoSelectAll, value), + .. self + } + } + + #[inline] + pub fn enter_returns_true(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_EnterReturnsTrue, value), + .. self + } + } + + #[inline] + pub fn callback_completion(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CallbackCompletion, value), + .. self + } + } + + #[inline] + pub fn callback_history(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CallbackHistory, value), + .. self + } + } + + #[inline] + pub fn callback_always(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CallbackAlways, value), + .. self + } + } + + #[inline] + pub fn callback_char_filter(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_CallbackCharFilter, value), + .. self + } + } + + #[inline] + pub fn allow_tab_input(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_AllowTabInput, value), + .. self + } + } + + #[inline] + pub fn no_horizontal_scroll(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_NoHorizontalScroll, value), + .. self + } + } + + #[inline] + pub fn always_insert_mode(self, value: bool) -> Self { + InputText { + flags: self.flags.with(ImGuiInputTextFlags_AlwaysInsertMode, value), + .. self + } + } + + // TODO: boxed closure...? + // pub fn callback(self) -> Self { } + + pub fn build(self) -> bool { + unsafe { + imgui_sys::igInputText( + self.label.as_ptr(), + // TODO: this is evil. Perhaps something else than &mut str is better + self.buf.as_ptr() as *mut i8, + self.buf.len() as size_t, + self.flags, + None, + ptr::null_mut()) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index ca7cacc..1b23d45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -499,26 +499,38 @@ impl<'ui> Ui<'ui> { //Widgets: Combos impl<'ui> Ui<'ui> { - pub fn combo<'p>(&self, label : ImStr<'p>, current_item : &mut i32, items : &mut Vec>, items_count : i32, height_in_items : i32) -> bool{ + pub fn combo<'p>(&self, + label: ImStr<'p>, + current_item: &mut i32, + items: &'p [ImStr<'p>], + height_in_items: i32) + -> bool { let items_inner : Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect(); unsafe { - imgui_sys::igCombo(label.as_ptr(), current_item, items_inner.as_ptr() as *mut *const c_char, items_count, height_in_items) - } - } - - pub fn combo2<'p>(&self, label : ImStr<'p>, current_item :&mut i32, items : ImStr<'p>, height_in_items : i32) -> bool { - unsafe{ - imgui_sys::igCombo2(label.as_ptr(), current_item, items.as_ptr(), height_in_items) + imgui_sys::igCombo(label.as_ptr(), + current_item, + items_inner.as_ptr() as *mut *const c_char, + items_inner.len() as i32, + height_in_items) } } } //Widgets: ListBox impl<'ui> Ui<'ui> { - pub fn list_box<'p>(&self, label : ImStr<'p>, current_item : &mut i32, items : &mut Vec>, items_count : i32, height_in_items : i32)-> bool{ - let items_inner : Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect(); + pub fn list_box<'p>(&self, + label: ImStr<'p>, + current_item: &mut i32, + items: &'p [ImStr<'p>], + height_in_items: i32) + -> bool{ + let items_inner : Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect(); unsafe{ - imgui_sys::igListBox(label.as_ptr(), current_item, items_inner.as_ptr() as *mut *const c_char,items_count, height_in_items) + imgui_sys::igListBox(label.as_ptr(), + current_item, + items_inner.as_ptr() as *mut *const c_char, + items_inner.len() as i32, + height_in_items) } } } diff --git a/src/menus.rs.bk b/src/menus.rs.bk new file mode 100644 index 0000000..2c80535 --- /dev/null +++ b/src/menus.rs.bk @@ -0,0 +1,87 @@ +use imgui_sys; +use std::marker::PhantomData; +use std::ptr; + +use super::{Ui, ImStr}; + +#[must_use] +pub struct Menu<'ui, 'p> { + label: ImStr<'p>, + enabled: bool, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> Menu<'ui, 'p> { + pub fn new(label: ImStr<'p>) -> Self { + Menu { + label: label, + enabled: true, + _phantom: PhantomData + } + } + #[inline] + pub fn enabled(self, enabled: bool) -> Self { + Menu { + enabled: enabled, + .. self + } + } + pub fn build(self, f: F) { + let render = unsafe { imgui_sys::igBeginMenu(self.label.as_ptr(), self.enabled) }; + if render { + f(); + unsafe { imgui_sys::igEndMenu() }; + } + } +} + +#[must_use] +pub struct MenuItem<'ui, 'p> { + label: ImStr<'p>, + shortcut: Option>, + selected: Option<&'p mut bool>, + enabled: bool, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> MenuItem<'ui, 'p> { + pub fn new(label: ImStr<'p>) -> Self { + MenuItem { + label: label, + shortcut: None, + selected: None, + enabled: true, + _phantom: PhantomData + } + } + #[inline] + pub fn shortcut(self, shortcut: ImStr<'p>) -> Self { + MenuItem { + shortcut: Some(shortcut), + .. self + } + } + #[inline] + pub fn selected(self, selected: &'p mut bool) -> Self { + MenuItem { + selected: Some(selected), + .. self + } + } + #[inline] + 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.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()); + let enabled = self.enabled; + unsafe { + imgui_sys::igMenuItemPtr(label, shortcut, selected, enabled) + } + } +} diff --git a/src/sliders.rs.bk b/src/sliders.rs.bk new file mode 100644 index 0000000..ea80399 --- /dev/null +++ b/src/sliders.rs.bk @@ -0,0 +1,91 @@ +use imgui_sys; +use std::marker::PhantomData; + +use super::{Ui, ImStr}; + +// TODO: Consider using Range, even though it is half-open + +#[must_use] +pub struct SliderInt<'ui, 'p> { + label: ImStr<'p>, + value: &'p mut i32, + min: i32, + max: i32, + display_format: ImStr<'p>, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> SliderInt<'ui, 'p> { + pub fn new(label: ImStr<'p>, value: &'p mut i32, min: i32, max: i32) -> Self { + SliderInt { + label: label, + value: value, + min: min, + max: max, + display_format: unsafe { ImStr::from_bytes_unchecked(b"%.0f\0") }, + _phantom: PhantomData + } + } + #[inline] + pub fn display_format(self, display_format: ImStr<'p>) -> Self { + SliderInt { + display_format: display_format, + .. self + } + } + pub fn build(self) -> bool { + unsafe { + imgui_sys::igSliderInt(self.label.as_ptr(), self.value, self.min, self.max, + self.display_format.as_ptr() + ) + } + } +} + +#[must_use] +pub struct SliderFloat<'ui, 'p> { + label: ImStr<'p>, + value: &'p mut f32, + min: f32, + max: f32, + display_format: ImStr<'p>, + power: f32, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> SliderFloat<'ui, 'p> { + pub fn new(label: ImStr<'p>, value: &'p mut f32, min: f32, max: f32) -> Self { + SliderFloat { + label: label, + value: value, + min: min, + max: max, + display_format: unsafe { ImStr::from_bytes_unchecked(b"%.3f\0") }, + power: 1.0, + _phantom: PhantomData + } + } + #[inline] + pub fn display_format(self, display_format: ImStr<'p>) -> Self { + SliderFloat { + display_format: display_format, + .. self + } + } + #[inline] + pub fn power(self, power: f32) -> Self { + SliderFloat { + power: power, + .. self + } + } + pub fn build(self) -> bool { + unsafe { + imgui_sys::igSliderFloat(self.label.as_ptr(), self.value, self.min, self.max, + self.display_format.as_ptr(), + self.power + ) + } + } +} + diff --git a/src/trees.rs.bk b/src/trees.rs.bk new file mode 100644 index 0000000..975c7f8 --- /dev/null +++ b/src/trees.rs.bk @@ -0,0 +1,56 @@ +use imgui_sys; +use std::marker::PhantomData; + +use super::{Ui, ImGuiSetCond, ImStr}; + +#[must_use] +pub struct TreeNode<'ui, 'p> { + id: ImStr<'p>, + label: Option>, + opened: bool, + opened_cond: ImGuiSetCond, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> TreeNode<'ui, 'p> { + pub fn new(id: ImStr<'p>) -> Self { + TreeNode { + id: id, + label: None, + opened: false, + opened_cond: ImGuiSetCond::empty(), + _phantom: PhantomData + } + } + #[inline] + pub fn label(self, label: ImStr<'p>) -> Self { + TreeNode { + label: Some(label), + .. self + } + } + #[inline] + pub fn opened(self, opened: bool, cond: ImGuiSetCond) -> Self { + TreeNode { + opened: opened, + opened_cond: cond, + .. self + } + } + pub fn build(self, f: F) { + let render = unsafe { + if !self.opened_cond.is_empty() { + imgui_sys::igSetNextTreeNodeOpened(self.opened, self.opened_cond); + } + imgui_sys::igTreeNodeStr( + self.id.as_ptr(), + super::fmt_ptr(), + self.label.unwrap_or(self.id).as_ptr() + ) + }; + if render { + f(); + unsafe { imgui_sys::igTreePop() }; + } + } +} diff --git a/src/widgets.rs.bk b/src/widgets.rs.bk new file mode 100644 index 0000000..8c4c740 --- /dev/null +++ b/src/widgets.rs.bk @@ -0,0 +1,57 @@ +use imgui_sys; +use std::marker::PhantomData; +use std::ptr; + +use super::{Ui, ImStr}; + +#[must_use] +pub struct CollapsingHeader<'ui, 'p> { + label: ImStr<'p>, + str_id: Option>, + display_frame: bool, + default_open: bool, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> CollapsingHeader<'ui, 'p> { + pub fn new(label: ImStr<'p>) -> Self { + CollapsingHeader { + label: label, + str_id: None, + display_frame: true, + default_open: false, + _phantom: PhantomData + } + } + #[inline] + pub fn str_id(self, str_id: ImStr<'p>) -> Self { + CollapsingHeader { + str_id: Some(str_id), + .. self + } + } + #[inline] + pub fn display_frame(self, display_frame: bool) -> Self { + CollapsingHeader { + display_frame: display_frame, + .. self + } + } + #[inline] + pub fn default_open(self, default_open: bool) -> Self { + CollapsingHeader { + default_open: default_open, + .. self + } + } + pub fn build(self) -> bool { + unsafe { + imgui_sys::igCollapsingHeader( + self.label.as_ptr(), + self.str_id.map(|x| x.as_ptr()).unwrap_or(ptr::null()), + self.display_frame, + self.default_open + ) + } + } +} diff --git a/src/window.rs.bk b/src/window.rs.bk new file mode 100644 index 0000000..b815073 --- /dev/null +++ b/src/window.rs.bk @@ -0,0 +1,200 @@ +use imgui_sys; +use std::marker::PhantomData; +use std::ptr; + +use super::{ + Ui, + ImGuiSetCond, + ImGuiWindowFlags, + ImGuiWindowFlags_NoTitleBar, ImGuiWindowFlags_NoResize, ImGuiWindowFlags_NoMove, + ImGuiWindowFlags_NoScrollbar, ImGuiWindowFlags_NoScrollWithMouse, ImGuiWindowFlags_NoCollapse, + ImGuiWindowFlags_AlwaysAutoResize, ImGuiWindowFlags_ShowBorders, + ImGuiWindowFlags_NoSavedSettings, ImGuiWindowFlags_NoInputs, ImGuiWindowFlags_MenuBar, + ImGuiWindowFlags_HorizontalScrollbar, ImGuiWindowFlags_NoFocusOnAppearing, + ImGuiWindowFlags_NoBringToFrontOnFocus, + ImStr, ImVec2 +}; + +#[must_use] +pub struct Window<'ui, 'p> { + pos: (f32, f32), + pos_cond: ImGuiSetCond, + size: (f32, f32), + size_cond: ImGuiSetCond, + name: ImStr<'p>, + opened: Option<&'p mut bool>, + bg_alpha: f32, + flags: ImGuiWindowFlags, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> Window<'ui, 'p> { + pub fn new(name: ImStr<'p>) -> Window<'ui, 'p> { + Window { + pos: (0.0, 0.0), + pos_cond: ImGuiSetCond::empty(), + size: (0.0, 0.0), + size_cond: ImGuiSetCond::empty(), + name: name, + opened: None, + bg_alpha: -1.0, + flags: ImGuiWindowFlags::empty(), + _phantom: PhantomData + } + } + #[inline] + pub fn position(self, pos: (f32, f32), cond: ImGuiSetCond) -> Self { + Window { + pos: pos, + pos_cond: cond, + .. self + } + } + #[inline] + pub fn size(self, size: (f32, f32), cond: ImGuiSetCond) -> Self { + Window { + size: size, + size_cond: cond, + .. self + } + } + #[inline] + pub fn opened(self, opened: &'p mut bool) -> Self { + Window { + opened: Some(opened), + .. self + } + } + #[inline] + pub fn bg_alpha(self, bg_alpha: f32) -> Self { + Window { + bg_alpha: bg_alpha, + .. self + } + } + #[inline] + pub fn flags(self, flags: ImGuiWindowFlags) -> Self { + Window { + flags: flags, + .. self + } + } + #[inline] + pub fn title_bar(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoTitleBar, !value), + .. self + } + } + #[inline] + pub fn resizable(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoResize, !value), + .. self + } + } + #[inline] + pub fn movable(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoMove, !value), + .. self + } + } + #[inline] + pub fn scroll_bar(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoScrollbar, !value), + .. self + } + } + #[inline] + pub fn scrollable(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoScrollWithMouse, !value), + .. self + } + } + #[inline] + pub fn collapsible(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoCollapse, !value), + .. self + } + } + #[inline] + pub fn always_auto_resize(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_AlwaysAutoResize, value), + .. self + } + } + #[inline] + pub fn show_borders(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_ShowBorders, value), + .. self + } + } + #[inline] + pub fn save_settings(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoSavedSettings, !value), + .. self + } + } + #[inline] + pub fn inputs(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoInputs, !value), + .. self + } + } + #[inline] + pub fn menu_bar(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_MenuBar, value), + .. self + } + } + #[inline] + pub fn horizontal_scrollbar(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_HorizontalScrollbar, value), + .. self + } + } + #[inline] + pub fn no_focus_on_appearing(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoFocusOnAppearing, value), + .. self + } + } + #[inline] + pub fn no_bring_to_front_on_focus(self, value: bool) -> Self { + Window { + flags: self.flags.with(ImGuiWindowFlags_NoBringToFrontOnFocus, value), + .. self + } + } + pub fn build(self, f: F) { + let render = unsafe { + if !self.pos_cond.is_empty() { + imgui_sys::igSetNextWindowPos(self.pos.into(), self.pos_cond); + } + if !self.size_cond.is_empty() { + imgui_sys::igSetNextWindowSize(self.size.into(), self.size_cond); + } + imgui_sys::igBegin2( + self.name.as_ptr(), + self.opened.map(|x| x as *mut bool).unwrap_or(ptr::null_mut()), + ImVec2::new(0.0, 0.0), + self.bg_alpha, + self.flags) + }; + if render { + f(); + } + unsafe { imgui_sys::igEnd() }; + } +}