Merge pull request #46 from Gekkio/feature/imstr-overhaul

Split ImStr to ImStr and ImString
This commit is contained in:
Joonas Javanainen 2017-04-26 00:16:40 +03:00 committed by GitHub
commit 64511f26bd
11 changed files with 240 additions and 146 deletions

View File

@ -4,7 +4,6 @@ extern crate imgui;
extern crate imgui_glium_renderer;
use imgui::*;
use std::iter::repeat;
use self::support::Support;
@ -31,10 +30,10 @@ struct State {
no_menu: bool,
bg_alpha: f32,
wrap_width: f32,
buf: String,
buf: ImString,
item: i32,
item2: i32,
text: String,
text: ImString,
i0: i32,
f0: f32,
vec2f: [f32; 2],
@ -50,13 +49,10 @@ struct State {
impl Default for State {
fn default() -> Self {
let mut buf = "日本語".to_owned();
buf.extend(repeat('\0').take(32));
buf.truncate(32);
let mut text = String::with_capacity(128);
let mut buf = ImString::with_capacity(32);
buf.push_str("日本語");
let mut text = ImString::with_capacity(128);
text.push_str("Hello, world!");
let remaining = text.capacity() - text.len();
text.extend(repeat('\0').take(remaining));
State {
clear_color: (114.0 / 255.0, 144.0 / 255.0, 154.0 / 255.0, 1.0),
show_app_metrics: false,

View File

@ -10,7 +10,7 @@ use super::{ImGuiInputTextFlags,
ImGuiInputTextFlags_CharsDecimal, ImGuiInputTextFlags_CharsHexadecimal,
ImGuiInputTextFlags_CharsNoBlank, ImGuiInputTextFlags_CharsUppercase,
ImGuiInputTextFlags_EnterReturnsTrue, ImGuiInputTextFlags_NoHorizontalScroll, ImStr,
Ui};
ImString, Ui};
macro_rules! impl_text_flags {
($InputType:ident) => {
@ -128,14 +128,14 @@ macro_rules! impl_precision_params {
#[must_use]
pub struct InputText<'ui, 'p> {
label: ImStr<'p>,
buf: &'p mut str,
label: &'p ImStr,
buf: &'p mut ImString,
flags: ImGuiInputTextFlags,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> InputText<'ui, 'p> {
pub fn new(label: ImStr<'p>, buf: &'p mut str) -> Self {
pub fn new(label: &'p ImStr, buf: &'p mut ImString) -> Self {
InputText {
label: label,
buf: buf,
@ -152,10 +152,8 @@ impl<'ui, 'p> InputText<'ui, 'p> {
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 usize,
self.buf.capacity_with_nul(),
self.flags,
None,
ptr::null_mut())
@ -165,7 +163,7 @@ impl<'ui, 'p> InputText<'ui, 'p> {
#[must_use]
pub struct InputInt<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut i32,
step: i32,
step_fast: i32,
@ -174,7 +172,7 @@ pub struct InputInt<'ui, 'p> {
}
impl<'ui, 'p> InputInt<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut i32) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut i32) -> Self {
InputInt {
label: label,
value: value,
@ -201,7 +199,7 @@ impl<'ui, 'p> InputInt<'ui, 'p> {
#[must_use]
pub struct InputFloat<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut f32,
step: f32,
step_fast: f32,
@ -211,7 +209,7 @@ pub struct InputFloat<'ui, 'p> {
}
impl<'ui, 'p> InputFloat<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut f32) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut f32) -> Self {
InputFloat {
label: label,
value: value,
@ -243,7 +241,7 @@ macro_rules! impl_input_floatn {
($InputFloatN:ident, $N:expr, $igInputFloatN:ident) => {
#[must_use]
pub struct $InputFloatN<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32;$N],
decimal_precision: i32,
flags: ImGuiInputTextFlags,
@ -251,7 +249,7 @@ macro_rules! impl_input_floatn {
}
impl<'ui, 'p> $InputFloatN<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [f32;$N]) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [f32;$N]) -> Self {
$InputFloatN {
label: label,
value: value,
@ -285,14 +283,14 @@ macro_rules! impl_input_intn {
($InputIntN:ident, $N:expr, $igInputIntN:ident) => {
#[must_use]
pub struct $InputIntN<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [i32;$N],
flags: ImGuiInputTextFlags,
_phantom: PhantomData<&'ui Ui<'ui>>
}
impl<'ui, 'p> $InputIntN<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [i32;$N]) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [i32;$N]) -> Self {
$InputIntN {
label: label,
value: value,
@ -321,13 +319,13 @@ impl_input_intn!(InputInt4, 4, igInputInt4);
#[must_use]
pub struct ColorEdit3<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 3],
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> ColorEdit3<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [f32; 3]) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [f32; 3]) -> Self {
ColorEdit3 {
label: label,
value: value,
@ -342,14 +340,14 @@ impl<'ui, 'p> ColorEdit3<'ui, 'p> {
#[must_use]
pub struct ColorEdit4<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 4],
show_alpha: bool,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> ColorEdit4<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [f32; 4]) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [f32; 4]) -> Self {
ColorEdit4 {
label: label,
value: value,

View File

@ -1,7 +1,5 @@
extern crate imgui_sys;
use std::borrow::Cow;
use std::convert::From;
use std::ffi::CStr;
use std::mem;
use std::os::raw::{c_char, c_float, c_int, c_uchar, c_void};
@ -45,6 +43,7 @@ pub use plotlines::PlotLines;
pub use progressbar::ProgressBar;
pub use sliders::{SliderFloat, SliderFloat2, SliderFloat3, SliderFloat4, SliderInt, SliderInt2,
SliderInt3, SliderInt4};
pub use string::{ImStr, ImString};
pub use trees::{CollapsingHeader, TreeNode};
pub use window::Window;
@ -54,54 +53,32 @@ mod plothistogram;
mod plotlines;
mod progressbar;
mod sliders;
mod string;
mod trees;
mod window;
pub struct ImGui {
// We need to keep ownership of the ImStr values to ensure the *const char pointer
// lives long enough in case the ImStr contains a Cow::Owned
ini_filename: Option<ImStr<'static>>,
log_filename: Option<ImStr<'static>>,
ini_filename: Option<ImString>,
log_filename: Option<ImString>,
}
#[macro_export]
macro_rules! im_str {
($e:tt) => ({
debug_assert!(!($e).as_bytes().contains(&0));
let value = concat!($e, "\0");
unsafe { ::imgui::ImStr::from_bytes_unchecked(value.as_bytes()) }
});
($e:tt, $($arg:tt)*) => ({
::imgui::ImStr::from(format!($e, $($arg)*))
let mut bytes: Vec<u8> = format!($e, $($arg)*).into();
debug_assert!(!bytes.contains(&0));
bytes.push(b'\0');
unsafe { &::imgui::ImString::from_vec_unchecked(bytes) }
})
}
#[derive(Clone)]
pub struct ImStr<'a> {
bytes: Cow<'a, [u8]>,
}
impl<'a> ImStr<'a> {
pub unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> ImStr<'a> {
ImStr { bytes: Cow::Borrowed(bytes) }
}
pub fn as_ptr(&self) -> *const c_char { self.bytes.as_ptr() as *const c_char }
}
impl<'a> From<&'a str> for ImStr<'a> {
fn from(value: &'a str) -> ImStr<'a> {
let mut bytes: Vec<u8> = value.bytes().collect();
bytes.push(0);
ImStr { bytes: Cow::Owned(bytes) }
}
}
impl From<String> for ImStr<'static> {
fn from(mut value: String) -> ImStr<'static> {
value.push('\0');
ImStr { bytes: Cow::Owned(value.into_bytes()) }
}
}
pub struct TextureHandle<'a> {
pub width: u32,
pub height: u32,
@ -153,7 +130,7 @@ impl ImGui {
(*self.io_mut().fonts).tex_id = value as *mut c_void;
}
}
pub fn set_ini_filename(&mut self, value: Option<ImStr<'static>>) {
pub fn set_ini_filename(&mut self, value: Option<ImString>) {
{
let io = self.io_mut();
io.ini_filename = match value {
@ -163,7 +140,7 @@ impl ImGui {
}
self.ini_filename = value;
}
pub fn set_log_filename(&mut self, value: Option<ImStr<'static>>) {
pub fn set_log_filename(&mut self, value: Option<ImString>) {
{
let io = self.io_mut();
io.log_filename = match value {
@ -394,7 +371,7 @@ impl<'a> Ui<'a> {
// Window
impl<'ui> Ui<'ui> {
pub fn window<'p>(&self, name: ImStr<'p>) -> Window<'ui, 'p> { Window::new(name) }
pub fn window<'p>(&self, name: &'p ImStr) -> Window<'ui, 'p> { Window::new(name) }
}
// Layout
@ -424,7 +401,7 @@ impl<'ui> Ui<'ui> {
}
pub fn spacing(&self) { unsafe { imgui_sys::igSpacing() }; }
pub fn columns<'p>(&self, count: i32, id: ImStr<'p>, border: bool) {
pub fn columns<'p>(&self, count: i32, id: &'p ImStr, border: bool) {
unsafe { imgui_sys::igColumns(count, id.as_ptr(), border) }
}
@ -470,30 +447,30 @@ impl<'ui> Ui<'ui> {
// Widgets
impl<'ui> Ui<'ui> {
pub fn text<'p>(&self, text: ImStr<'p>) {
pub fn text<P: AsRef<ImStr>>(&self, text: P) {
// TODO: use igTextUnformatted
unsafe {
imgui_sys::igText(fmt_ptr(), text.as_ptr());
imgui_sys::igText(fmt_ptr(), text.as_ref().as_ptr());
}
}
pub fn text_colored<'p, A>(&self, col: A, text: ImStr<'p>)
pub fn text_colored<'p, A>(&self, col: A, text: &'p ImStr)
where A: Into<ImVec4>
{
unsafe {
imgui_sys::igTextColored(col.into(), fmt_ptr(), text.as_ptr());
}
}
pub fn text_disabled<'p>(&self, text: ImStr<'p>) {
pub fn text_disabled<'p>(&self, text: &'p ImStr) {
unsafe {
imgui_sys::igTextDisabled(fmt_ptr(), text.as_ptr());
}
}
pub fn text_wrapped<'p>(&self, text: ImStr<'p>) {
pub fn text_wrapped<'p>(&self, text: &'p ImStr) {
unsafe {
imgui_sys::igTextWrapped(fmt_ptr(), text.as_ptr());
}
}
pub fn label_text<'p>(&self, label: ImStr<'p>, text: ImStr<'p>) {
pub fn label_text<'p>(&self, label: &'p ImStr, text: &'p ImStr) {
unsafe {
imgui_sys::igLabelText(label.as_ptr(), fmt_ptr(), text.as_ptr());
}
@ -503,18 +480,18 @@ impl<'ui> Ui<'ui> {
imgui_sys::igBullet();
}
}
pub fn bullet_text<'p>(&self, text: ImStr<'p>) {
pub fn bullet_text<'p>(&self, text: &'p ImStr) {
unsafe {
imgui_sys::igBulletText(fmt_ptr(), text.as_ptr());
}
}
pub fn button<'p>(&self, label: ImStr<'p>, size: ImVec2) -> bool {
pub fn button<'p>(&self, label: &'p ImStr, size: ImVec2) -> bool {
unsafe { imgui_sys::igButton(label.as_ptr(), size) }
}
pub fn small_button<'p>(&self, label: ImStr<'p>) -> bool {
pub fn small_button<'p>(&self, label: &'p ImStr) -> bool {
unsafe { imgui_sys::igSmallButton(label.as_ptr()) }
}
pub fn checkbox<'p>(&self, label: ImStr<'p>, value: &'p mut bool) -> bool {
pub fn checkbox<'p>(&self, label: &'p ImStr, value: &'p mut bool) -> bool {
unsafe { imgui_sys::igCheckbox(label.as_ptr(), value) }
}
}
@ -522,51 +499,51 @@ impl<'ui> Ui<'ui> {
// Widgets: Input
impl<'ui> Ui<'ui> {
pub fn color_edit3<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 3])
-> ColorEdit3<'ui, 'p> {
ColorEdit3::new(label, value)
}
pub fn color_edit4<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 4])
-> ColorEdit4<'ui, 'p> {
ColorEdit4::new(label, value)
}
pub fn input_text<'p>(&self, label: ImStr<'p>, buf: &'p mut str) -> InputText<'ui, 'p> {
pub fn input_text<'p>(&self, label: &'p ImStr, buf: &'p mut ImString) -> InputText<'ui, 'p> {
InputText::new(label, buf)
}
pub fn input_float<'p>(&self, label: ImStr<'p>, value: &'p mut f32) -> InputFloat<'ui, 'p> {
pub fn input_float<'p>(&self, label: &'p ImStr, value: &'p mut f32) -> InputFloat<'ui, 'p> {
InputFloat::new(label, value)
}
pub fn input_float2<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 2])
-> InputFloat2<'ui, 'p> {
InputFloat2::new(label, value)
}
pub fn input_float3<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 3])
-> InputFloat3<'ui, 'p> {
InputFloat3::new(label, value)
}
pub fn input_float4<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 4])
-> InputFloat4<'ui, 'p> {
InputFloat4::new(label, value)
}
pub fn input_int<'p>(&self, label: ImStr<'p>, value: &'p mut i32) -> InputInt<'ui, 'p> {
pub fn input_int<'p>(&self, label: &'p ImStr, value: &'p mut i32) -> InputInt<'ui, 'p> {
InputInt::new(label, value)
}
pub fn input_int2<'p>(&self, label: ImStr<'p>, value: &'p mut [i32; 2]) -> InputInt2<'ui, 'p> {
pub fn input_int2<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 2]) -> InputInt2<'ui, 'p> {
InputInt2::new(label, value)
}
pub fn input_int3<'p>(&self, label: ImStr<'p>, value: &'p mut [i32; 3]) -> InputInt3<'ui, 'p> {
pub fn input_int3<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 3]) -> InputInt3<'ui, 'p> {
InputInt3::new(label, value)
}
pub fn input_int4<'p>(&self, label: ImStr<'p>, value: &'p mut [i32; 4]) -> InputInt4<'ui, 'p> {
pub fn input_int4<'p>(&self, label: &'p ImStr, value: &'p mut [i32; 4]) -> InputInt4<'ui, 'p> {
InputInt4::new(label, value)
}
}
@ -574,7 +551,7 @@ impl<'ui> Ui<'ui> {
// Widgets: Sliders
impl<'ui> Ui<'ui> {
pub fn slider_float<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut f32,
min: f32,
max: f32)
@ -582,7 +559,7 @@ impl<'ui> Ui<'ui> {
SliderFloat::new(label, value, min, max)
}
pub fn slider_float2<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 2],
min: f32,
max: f32)
@ -590,7 +567,7 @@ impl<'ui> Ui<'ui> {
SliderFloat2::new(label, value, min, max)
}
pub fn slider_float3<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 3],
min: f32,
max: f32)
@ -598,7 +575,7 @@ impl<'ui> Ui<'ui> {
SliderFloat3::new(label, value, min, max)
}
pub fn slider_float4<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; 4],
min: f32,
max: f32)
@ -606,7 +583,7 @@ impl<'ui> Ui<'ui> {
SliderFloat4::new(label, value, min, max)
}
pub fn slider_int<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut i32,
min: i32,
max: i32)
@ -614,7 +591,7 @@ impl<'ui> Ui<'ui> {
SliderInt::new(label, value, min, max)
}
pub fn slider_int2<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [i32; 2],
min: i32,
max: i32)
@ -622,7 +599,7 @@ impl<'ui> Ui<'ui> {
SliderInt2::new(label, value, min, max)
}
pub fn slider_int3<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [i32; 3],
min: i32,
max: i32)
@ -630,7 +607,7 @@ impl<'ui> Ui<'ui> {
SliderInt3::new(label, value, min, max)
}
pub fn slider_int4<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [i32; 4],
min: i32,
max: i32)
@ -641,8 +618,8 @@ impl<'ui> Ui<'ui> {
// Widgets: Trees
impl<'ui> Ui<'ui> {
pub fn tree_node<'p>(&self, id: ImStr<'p>) -> TreeNode<'ui, 'p> { TreeNode::new(id) }
pub fn collapsing_header<'p>(&self, label: ImStr<'p>) -> CollapsingHeader<'ui, 'p> {
pub fn tree_node<'p>(&self, id: &'p ImStr) -> TreeNode<'ui, 'p> { TreeNode::new(id) }
pub fn collapsing_header<'p>(&self, label: &'p ImStr) -> CollapsingHeader<'ui, 'p> {
CollapsingHeader::new(label)
}
}
@ -650,7 +627,7 @@ impl<'ui> Ui<'ui> {
// Widgets: Selectable / Lists
impl<'ui> Ui<'ui> {
pub fn selectable<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
selected: bool,
flags: ImGuiSelectableFlags,
size: ImVec2)
@ -679,16 +656,16 @@ impl<'ui> Ui<'ui> {
unsafe { imgui_sys::igEndMenuBar() };
}
}
pub fn menu<'p>(&self, label: ImStr<'p>) -> Menu<'ui, 'p> { Menu::new(label) }
pub fn menu_item<'p>(&self, label: ImStr<'p>) -> MenuItem<'ui, 'p> { MenuItem::new(label) }
pub fn menu<'p>(&self, label: &'p ImStr) -> Menu<'ui, 'p> { Menu::new(label) }
pub fn menu_item<'p>(&self, label: &'p ImStr) -> MenuItem<'ui, 'p> { MenuItem::new(label) }
}
// Widgets: Popups
impl<'ui> Ui<'ui> {
pub fn open_popup<'p>(&self, str_id: ImStr<'p>) {
pub fn open_popup<'p>(&self, str_id: &'p ImStr) {
unsafe { imgui_sys::igOpenPopup(str_id.as_ptr()) };
}
pub fn popup<'p, F>(&self, str_id: ImStr<'p>, f: F)
pub fn popup<'p, F>(&self, str_id: &'p ImStr, f: F)
where F: FnOnce()
{
let render = unsafe { imgui_sys::igBeginPopup(str_id.as_ptr()) };
@ -703,9 +680,9 @@ impl<'ui> Ui<'ui> {
// Widgets: Combos
impl<'ui> Ui<'ui> {
pub fn combo<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
current_item: &mut i32,
items: &'p [ImStr<'p>],
items: &'p [&'p ImStr],
height_in_items: i32)
-> bool {
let items_inner: Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect();
@ -722,9 +699,9 @@ impl<'ui> Ui<'ui> {
// Widgets: ListBox
impl<'ui> Ui<'ui> {
pub fn list_box<'p>(&self,
label: ImStr<'p>,
label: &'p ImStr,
current_item: &mut i32,
items: &'p [ImStr<'p>],
items: &'p [&'p ImStr],
height_in_items: i32)
-> bool {
let items_inner: Vec<*const c_char> = items.into_iter().map(|item| item.as_ptr()).collect();
@ -739,13 +716,13 @@ impl<'ui> Ui<'ui> {
}
impl<'ui> Ui<'ui> {
pub fn plot_lines<'p>(&self, label: ImStr<'p>, values: &'p [f32]) -> PlotLines<'p> {
pub fn plot_lines<'p>(&self, label: &'p ImStr, values: &'p [f32]) -> PlotLines<'p> {
PlotLines::new(label, values)
}
}
impl<'ui> Ui<'ui> {
pub fn plot_histogram<'p>(&self, label: ImStr<'p>, values: &'p [f32]) -> PlotHistogram<'p> {
pub fn plot_histogram<'p>(&self, label: &'p ImStr, values: &'p [f32]) -> PlotHistogram<'p> {
PlotHistogram::new(label, values)
}
}

View File

@ -6,13 +6,13 @@ use super::{ImStr, Ui};
#[must_use]
pub struct Menu<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
enabled: bool,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> Menu<'ui, 'p> {
pub fn new(label: ImStr<'p>) -> Self {
pub fn new(label: &'p ImStr) -> Self {
Menu {
label: label,
enabled: true,
@ -35,15 +35,15 @@ impl<'ui, 'p> Menu<'ui, 'p> {
#[must_use]
pub struct MenuItem<'ui, 'p> {
label: ImStr<'p>,
shortcut: Option<ImStr<'p>>,
label: &'p ImStr,
shortcut: Option<&'p ImStr>,
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 {
pub fn new(label: &'p ImStr) -> Self {
MenuItem {
label: label,
shortcut: None,
@ -53,7 +53,7 @@ impl<'ui, 'p> MenuItem<'ui, 'p> {
}
}
#[inline]
pub fn shortcut(mut self, shortcut: ImStr<'p>) -> Self {
pub fn shortcut(mut self, shortcut: &'p ImStr) -> Self {
self.shortcut = Some(shortcut);
self
}

View File

@ -6,17 +6,17 @@ use super::{ImStr, ImVec2};
#[must_use]
pub struct PlotHistogram<'p> {
label: ImStr<'p>,
label: &'p ImStr,
values: &'p [f32],
values_offset: usize,
overlay_text: Option<ImStr<'p>>,
overlay_text: Option<&'p ImStr>,
scale_min: f32,
scale_max: f32,
graph_size: ImVec2,
}
impl<'p> PlotHistogram<'p> {
pub fn new(label: ImStr<'p>, values: &'p [f32]) -> Self {
pub fn new(label: &'p ImStr, values: &'p [f32]) -> Self {
PlotHistogram {
label: label,
values: values,
@ -35,7 +35,7 @@ impl<'p> PlotHistogram<'p> {
}
#[inline]
pub fn overlay_text(mut self, overlay_text: ImStr<'p>) -> Self {
pub fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
self.overlay_text = Some(overlay_text);
self
}

View File

@ -5,17 +5,17 @@ use std::os::raw::c_float;
use super::{ImStr, ImVec2};
#[must_use]
pub struct PlotLines<'p> {
label: ImStr<'p>,
label: &'p ImStr,
values: &'p [f32],
values_offset: usize,
overlay_text: Option<ImStr<'p>>,
overlay_text: Option<&'p ImStr>,
scale_min: f32,
scale_max: f32,
graph_size: ImVec2,
}
impl<'p> PlotLines<'p> {
pub fn new(label: ImStr<'p>, values: &'p [f32]) -> Self {
pub fn new(label: &'p ImStr, values: &'p [f32]) -> Self {
PlotLines {
label: label,
values: values,
@ -34,7 +34,7 @@ impl<'p> PlotLines<'p> {
}
#[inline]
pub fn overlay_text(mut self, overlay_text: ImStr<'p>) -> Self {
pub fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
self.overlay_text = Some(overlay_text);
self
}

View File

@ -10,7 +10,7 @@ use super::{ImStr, ImVec2};
pub struct ProgressBar<'p> {
fraction: f32,
size: ImVec2,
overlay_text: Option<ImStr<'p>>,
overlay_text: Option<&'p ImStr>,
}
impl<'p> ProgressBar<'p> {
@ -29,7 +29,7 @@ impl<'p> ProgressBar<'p> {
/// Sets an optional text that will be drawn over the progress bar.
#[inline]
pub fn overlay_text(mut self, overlay_text: ImStr<'p>) -> Self {
pub fn overlay_text(mut self, overlay_text: &'p ImStr) -> Self {
self.overlay_text = Some(overlay_text);
self
}

View File

@ -7,16 +7,16 @@ use super::{ImStr, Ui};
#[must_use]
pub struct SliderInt<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut i32,
min: i32,
max: i32,
display_format: ImStr<'p>,
display_format: &'p ImStr,
_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 {
pub fn new(label: &'p ImStr, value: &'p mut i32, min: i32, max: i32) -> Self {
SliderInt {
label: label,
value: value,
@ -27,7 +27,7 @@ impl<'ui, 'p> SliderInt<'ui, 'p> {
}
}
#[inline]
pub fn display_format(mut self, display_format: ImStr<'p>) -> Self {
pub fn display_format(mut self, display_format: &'p ImStr) -> Self {
self.display_format = display_format;
self
}
@ -46,16 +46,16 @@ macro_rules! impl_slider_intn {
($SliderIntN:ident, $N:expr, $igSliderIntN:ident) => {
#[must_use]
pub struct $SliderIntN<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [i32; $N],
min: i32,
max: i32,
display_format: ImStr<'p>,
display_format: &'p ImStr,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> $SliderIntN<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [i32; $N], min: i32, max: i32) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [i32; $N], min: i32, max: i32) -> Self {
$SliderIntN {
label: label,
value: value,
@ -66,7 +66,7 @@ macro_rules! impl_slider_intn {
}
}
#[inline]
pub fn display_format(mut self, display_format: ImStr<'p>) -> Self {
pub fn display_format(mut self, display_format: &'p ImStr) -> Self {
self.display_format = display_format;
self
}
@ -90,17 +90,17 @@ impl_slider_intn!(SliderInt4, 4, igSliderInt4);
#[must_use]
pub struct SliderFloat<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut f32,
min: f32,
max: f32,
display_format: ImStr<'p>,
display_format: &'p ImStr,
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 {
pub fn new(label: &'p ImStr, value: &'p mut f32, min: f32, max: f32) -> Self {
SliderFloat {
label: label,
value: value,
@ -112,7 +112,7 @@ impl<'ui, 'p> SliderFloat<'ui, 'p> {
}
}
#[inline]
pub fn display_format(mut self, display_format: ImStr<'p>) -> Self {
pub fn display_format(mut self, display_format: &'p ImStr) -> Self {
self.display_format = display_format;
self
}
@ -137,17 +137,17 @@ macro_rules! impl_slider_floatn {
($SliderFloatN:ident, $N:expr, $igSliderFloatN:ident) => {
#[must_use]
pub struct $SliderFloatN<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
value: &'p mut [f32; $N],
min: f32,
max: f32,
display_format: ImStr<'p>,
display_format: &'p ImStr,
power: f32,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> $SliderFloatN<'ui, 'p> {
pub fn new(label: ImStr<'p>, value: &'p mut [f32; $N], min: f32, max: f32) -> Self {
pub fn new(label: &'p ImStr, value: &'p mut [f32; $N], min: f32, max: f32) -> Self {
$SliderFloatN {
label: label,
value: value,
@ -159,7 +159,7 @@ macro_rules! impl_slider_floatn {
}
}
#[inline]
pub fn display_format(mut self, display_format: ImStr<'p>) -> Self {
pub fn display_format(mut self, display_format: &'p ImStr) -> Self {
self.display_format = display_format;
self
}

123
src/string.rs Normal file
View File

@ -0,0 +1,123 @@
use std::borrow::Borrow;
use std::ffi::{CStr, CString, NulError};
use std::fmt;
use std::mem;
use std::ops::Deref;
use std::os::raw::c_char;
use std::str;
#[derive(Clone, Default, Hash, Ord, Eq, PartialOrd, PartialEq)]
pub struct ImString(Vec<u8>);
impl ImString {
pub fn new<T: Into<String>>(t: T) -> Result<ImString, NulError> {
CString::new(t.into()).map(|cstring| ImString(cstring.into_bytes_with_nul()))
}
pub fn with_capacity(capacity: usize) -> ImString {
let mut v = Vec::with_capacity(capacity + 1);
v.push(b'\0');
ImString(v)
}
pub unsafe fn from_string_unchecked(s: String) -> ImString {
ImString::from_vec_unchecked(s.into())
}
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> ImString {
v.push(b'\0');
ImString(v)
}
pub fn clear(&mut self) {
self.0.clear();
self.0.push(b'\0');
}
pub fn push_str(&mut self, string: &str) {
self.0.pop();
self.0.extend_from_slice(string.as_bytes());
self.0.push(b'\0');
}
pub fn capacity(&self) -> usize { self.0.capacity() - 1 }
pub fn capacity_with_nul(&self) -> usize { self.0.capacity() }
pub fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
pub fn reserve_exact(&mut self, additional: usize) {
self.0.reserve_exact(additional);
}
}
impl AsRef<ImStr> for ImString {
fn as_ref(&self) -> &ImStr { self }
}
impl Borrow<ImStr> for ImString {
fn borrow(&self) -> &ImStr { self }
}
impl fmt::Debug for ImString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s: &str = self;
fmt::Debug::fmt(s, f)
}
}
impl Deref for ImString {
type Target = ImStr;
fn deref(&self) -> &ImStr {
// as_ptr() is used, because we need to look at the bytes to figure out the length
// self.0.len() is incorrect, because there might be more than one nul byte in the end
unsafe { mem::transmute(CStr::from_ptr(self.0.as_ptr() as *const c_char)) }
}
}
impl<'a> From<&'a ImStr> for ImString {
fn from(value: &'a ImStr) -> ImString { value.to_owned() }
}
#[derive(Hash)]
pub struct ImStr(CStr);
impl<'a> Default for &'a ImStr {
fn default() -> &'a ImStr {
static SLICE: &'static [u8] = &[0];
unsafe { ImStr::from_bytes_unchecked(SLICE) }
}
}
impl fmt::Debug for ImStr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl ImStr {
pub unsafe fn from_bytes_unchecked<'a>(bytes: &'a [u8]) -> &'a ImStr {
mem::transmute(bytes)
}
pub fn as_ptr(&self) -> *const c_char { self.0.as_ptr() as *const c_char }
pub fn to_str(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.as_bytes()) }
}
}
impl<'a> Into<&'a CStr> for &'a ImStr {
fn into(self) -> &'a CStr { &self.0 }
}
impl AsRef<CStr> for ImStr {
fn as_ref(&self) -> &CStr { &self.0 }
}
impl AsRef<ImStr> for ImStr {
fn as_ref(&self) -> &ImStr { self }
}
impl ToOwned for ImStr {
type Owned = ImString;
fn to_owned(&self) -> ImString { ImString(self.0.to_owned().into_bytes()) }
}
impl Deref for ImStr {
type Target = str;
fn deref(&self) -> &str {
unsafe { str::from_utf8_unchecked(self.0.to_bytes()) }
}
}

View File

@ -8,15 +8,15 @@ use super::{ImGuiSetCond, ImGuiTreeNodeFlags, ImGuiTreeNodeFlags_Bullet,
#[must_use]
pub struct TreeNode<'ui, 'p> {
id: ImStr<'p>,
label: Option<ImStr<'p>>,
id: &'p ImStr,
label: Option<&'p ImStr>,
opened: bool,
opened_cond: ImGuiSetCond,
_phantom: PhantomData<&'ui Ui<'ui>>,
}
impl<'ui, 'p> TreeNode<'ui, 'p> {
pub fn new(id: ImStr<'p>) -> Self {
pub fn new(id: &'p ImStr) -> Self {
TreeNode {
id: id,
label: None,
@ -26,7 +26,7 @@ impl<'ui, 'p> TreeNode<'ui, 'p> {
}
}
#[inline]
pub fn label(mut self, label: ImStr<'p>) -> Self {
pub fn label(mut self, label: &'p ImStr) -> Self {
self.label = Some(label);
self
}
@ -54,7 +54,7 @@ impl<'ui, 'p> TreeNode<'ui, 'p> {
#[must_use]
pub struct CollapsingHeader<'ui, 'p> {
label: ImStr<'p>,
label: &'p ImStr,
// Some flags are automatically set in ImGui::CollapsingHeader, so
// we only support a sensible subset here
flags: ImGuiTreeNodeFlags,
@ -62,7 +62,7 @@ pub struct CollapsingHeader<'ui, 'p> {
}
impl<'ui, 'p> CollapsingHeader<'ui, 'p> {
pub fn new(label: ImStr<'p>) -> Self {
pub fn new(label: &'p ImStr) -> Self {
CollapsingHeader {
label: label,
flags: ImGuiTreeNodeFlags::empty(),

View File

@ -18,7 +18,7 @@ pub struct Window<'ui, 'p> {
pos_cond: ImGuiSetCond,
size: (f32, f32),
size_cond: ImGuiSetCond,
name: ImStr<'p>,
name: &'p ImStr,
opened: Option<&'p mut bool>,
bg_alpha: f32,
flags: ImGuiWindowFlags,
@ -26,7 +26,7 @@ pub struct Window<'ui, 'p> {
}
impl<'ui, 'p> Window<'ui, 'p> {
pub fn new(name: ImStr<'p>) -> Window<'ui, 'p> {
pub fn new(name: &'p ImStr) -> Window<'ui, 'p> {
Window {
pos: (0.0, 0.0),
pos_cond: ImGuiSetCond::empty(),