Removed im_str and ImString usage
This commit is contained in:
parent
f132811e93
commit
4401d696b1
12 changed files with 248 additions and 192 deletions
|
@ -1,11 +1,11 @@
|
|||
//! This example demonstrates how bar plots are to be used. For more general
|
||||
//! features of the libray, see the line_plots example.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{Plot, PlotBars, PlotUi};
|
||||
|
||||
pub fn show_basic_vertical_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This header shows a simple vertical bar plot."));
|
||||
ui.text("This header shows a simple vertical bar plot.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Vertical bar plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -22,7 +22,7 @@ pub fn show_basic_vertical_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_basic_horizontal_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This header shows a simple horizontal bar plot."));
|
||||
ui.text("This header shows a simple horizontal bar plot.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Horizontal bar plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -40,10 +40,10 @@ pub fn show_basic_horizontal_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Bar plots: Basic vertical")).build(&ui) {
|
||||
show_basic_vertical_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Bar plots: Basic vertical").build(ui) {
|
||||
show_basic_vertical_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Bar plots: Basic horizontal")).build(&ui) {
|
||||
show_basic_horizontal_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Bar plots: Basic horizontal").build(ui) {
|
||||
show_basic_horizontal_plot(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! This example demonstrates how heatmaps are to be used. For more general
|
||||
//! features of the libray, see the line_plots example.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{ImPlotPoint, Plot, PlotHeatmap, PlotUi};
|
||||
|
||||
pub fn show_basic_heatmap(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This header shows a simple heatmap"));
|
||||
ui.text("This header shows a simple heatmap");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Heatmap plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -25,7 +25,7 @@ pub fn show_basic_heatmap(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Heatmap: Basic")).build(&ui) {
|
||||
show_basic_heatmap(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Heatmap: Basic").build(ui) {
|
||||
show_basic_heatmap(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ pub mod stairs_plots;
|
|||
mod stem_plots;
|
||||
pub mod text_plots;
|
||||
|
||||
use imgui::{im_str, Condition, Ui, Window};
|
||||
use imgui::{Condition, Ui, Window};
|
||||
use implot::PlotUi;
|
||||
|
||||
/// State of the demo code
|
||||
|
@ -28,45 +28,51 @@ impl DemoState {
|
|||
// Most of the demos are currently still stateless, so the code here mostly just calls into
|
||||
// the modules. The line plots demo is stateful though. Things will be refactored soon to
|
||||
// make all the individual demos stateful to unify things more.
|
||||
Window::new(im_str!("implot-rs demo"))
|
||||
Window::new("implot-rs demo")
|
||||
.size([430.0, 450.0], Condition::FirstUseEver)
|
||||
.build(ui, || {
|
||||
ui.text(im_str!("Hello from implot-rs!"));
|
||||
ui.text_wrapped(im_str!(
|
||||
ui.text("Hello from implot-rs!");
|
||||
ui.text_wrapped(
|
||||
"The headers here demo the plotting features of the library.\
|
||||
Have a look at the example source code to see how they are implemented.\n\
|
||||
Check out the demo from ImPlot itself first for instructions on how to\
|
||||
interact with ImPlot plots."
|
||||
));
|
||||
interact with ImPlot plots.",
|
||||
);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Bar plots:"));
|
||||
ui.text("Bar plots:");
|
||||
bar_plots::show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Line plots:"));
|
||||
ui.text("Line plots:");
|
||||
// The line plots demo is stateful
|
||||
self.line_plots.show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Scatter plots:"));
|
||||
ui.text("Scatter plots:");
|
||||
scatter_plots::show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Text plots:"));
|
||||
ui.text("Text plots:");
|
||||
text_plots::show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Stairs plots:"));
|
||||
ui.text("Stairs plots:");
|
||||
stairs_plots::show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Heatmaps:"));
|
||||
ui.text("Heatmaps:");
|
||||
heatmaps::show_demo_headers(ui, plot_ui);
|
||||
|
||||
ui.separator();
|
||||
ui.text(im_str!("Stem plots:"));
|
||||
ui.text("Stem plots:");
|
||||
stem_plots::show_demo_headers(ui, plot_ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DemoState {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This example demonstrates how line plots are to be used, along with some querying features
|
||||
//! that will be applicable to all kinds of plots.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Condition, Ui};
|
||||
use imgui::{CollapsingHeader, Condition, Ui};
|
||||
use implot::{
|
||||
get_plot_limits, get_plot_mouse_position, get_plot_query, is_legend_entry_hovered,
|
||||
is_plot_hovered, is_plot_queried, pixels_to_plot_vec2, plot_to_pixels_vec2, push_style_color,
|
||||
|
@ -27,9 +27,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header just plots a line with as little code as possible."
|
||||
));
|
||||
ui.text("This header just plots a line with as little code as possible.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Simple line plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -44,9 +42,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_two_yaxis_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header shows how to create a plot with multiple Y axes."
|
||||
));
|
||||
ui.text("This header shows how to create a plot with multiple Y axes.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Multiple Y axis plots")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -79,7 +75,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_axis_equal_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This plot has axis equal set (1:1 aspect ratio)."));
|
||||
ui.text("This plot has axis equal set (1:1 aspect ratio).");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Axis equal line plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -95,9 +91,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_configurable_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header demos what we can configure about plots."
|
||||
));
|
||||
ui.text("This header demos what we can configure about plots.");
|
||||
|
||||
// Settings for the plot
|
||||
// - X and Y size in pixels
|
||||
|
@ -127,8 +121,8 @@ impl LinePlotDemoState {
|
|||
// Axis labels
|
||||
Plot::new("Configured line plot")
|
||||
.size([x_size, y_size])
|
||||
.x_label(&x_label)
|
||||
.y_label(&y_label)
|
||||
.x_label(x_label)
|
||||
.y_label(y_label)
|
||||
.x_limits(
|
||||
ImPlotRange {
|
||||
Min: x_min,
|
||||
|
@ -156,14 +150,12 @@ impl LinePlotDemoState {
|
|||
.with_y_axis_flags(YAxisChoice::First, &y_axis_flags)
|
||||
.with_legend_location(&PlotLocation::West, &PlotOrientation::Horizontal, true)
|
||||
.build(plot_ui, || {
|
||||
PlotLine::new("A line 2").plot(&vec![2.4, 2.9], &vec![1.1, 1.9]);
|
||||
PlotLine::new("A line 2").plot(&[2.4, 2.9], &[1.1, 1.9]);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn show_query_features_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header demos how to use the querying features."
|
||||
));
|
||||
ui.text("This header demos how to use the querying features.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
|
||||
// Create some containers for exfiltrating data from the closure below
|
||||
|
@ -202,8 +194,8 @@ impl LinePlotDemoState {
|
|||
));
|
||||
|
||||
// Plot a line so we have a legend entry
|
||||
PlotLine::new("Legend1").plot(&vec![2.0, 2.0], &vec![2.0, 1.0]);
|
||||
PlotLine::new("Legend2").plot(&vec![0.0, 0.0], &vec![1.0, 1.0]);
|
||||
PlotLine::new("Legend1").plot(&[2.0, 2.0], &[2.0, 1.0]);
|
||||
PlotLine::new("Legend2").plot(&[0.0, 0.0], &[1.0, 1.0]);
|
||||
legend1_hovered = is_legend_entry_hovered("Legend1");
|
||||
legend2_hovered = is_legend_entry_hovered("Legend2");
|
||||
|
||||
|
@ -217,43 +209,39 @@ impl LinePlotDemoState {
|
|||
// things like is_plot_hovered or get_plot_mouse_position() outside
|
||||
// of an actual Plot is not allowed.
|
||||
if let Some(pos) = hover_pos_plot {
|
||||
ui.text(im_str!("hovered at {}, {}", pos.x, pos.y));
|
||||
ui.text(format!("hovered at {}, {}", pos.x, pos.y));
|
||||
}
|
||||
if let Some(pixel_position) = hover_pos_pixels {
|
||||
// Try out converting plot mouse position to pixel position
|
||||
ui.text(im_str!(
|
||||
ui.text(format!(
|
||||
"pixel pos from plot: {}, {}",
|
||||
pixel_position.x,
|
||||
pixel_position.y
|
||||
pixel_position.x, pixel_position.y
|
||||
));
|
||||
ui.text(im_str!(
|
||||
ui.text(format!(
|
||||
"pixel pos from imgui: {}, {}",
|
||||
ui.io().mouse_pos[0],
|
||||
ui.io().mouse_pos[1]
|
||||
));
|
||||
}
|
||||
if let Some(limits) = plot_limits {
|
||||
ui.text(im_str!("Plot limits are {:#?}", limits));
|
||||
ui.text(format!("Plot limits are {:#?}", limits));
|
||||
}
|
||||
if let Some(query) = query_limits {
|
||||
ui.text(im_str!("Query limits are {:#?}", query));
|
||||
ui.text(format!("Query limits are {:#?}", query));
|
||||
}
|
||||
ui.text(im_str!(
|
||||
ui.text(format!(
|
||||
"Legend hovering - 1: {}, 2: {}",
|
||||
legend1_hovered,
|
||||
legend2_hovered
|
||||
legend1_hovered, legend2_hovered
|
||||
));
|
||||
|
||||
// Try out converting pixel position to plot position
|
||||
if let Some(pos) = hover_pos_from_pixels {
|
||||
ui.text(im_str!("plot pos from imgui: {}, {}", pos.x, pos.y,));
|
||||
ui.text(format!("plot pos from imgui: {}, {}", pos.x, pos.y,));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_style_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header demos how to use the styling features."
|
||||
));
|
||||
ui.text("This header demos how to use the styling features.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
|
||||
// The style stack works the same as for other imgui things - we can push
|
||||
|
@ -278,14 +266,14 @@ impl LinePlotDemoState {
|
|||
// Markers can be selected as shown here. The markers are internally represented
|
||||
// as an u32, hence this calling style.
|
||||
let markerchoice = push_style_var_i32(&StyleVar::Marker, Marker::Cross as i32);
|
||||
PlotLine::new("Left eye").plot(&vec![2.0, 2.0], &vec![2.0, 1.0]);
|
||||
PlotLine::new("Left eye").plot(&[2.0, 2.0], &[2.0, 1.0]);
|
||||
// Calling pop() on the return value of the push above will undo the marker choice.
|
||||
markerchoice.pop();
|
||||
|
||||
// Line weights can be set the same way, along with some other things - see
|
||||
// the docs of StyleVar for more info.
|
||||
let lineweight = push_style_var_f32(&StyleVar::LineWeight, 5.0);
|
||||
PlotLine::new("Right eye").plot(&vec![4.0, 4.0], &vec![2.0, 1.0]);
|
||||
PlotLine::new("Right eye").plot(&[4.0, 4.0], &[2.0, 1.0]);
|
||||
lineweight.pop();
|
||||
|
||||
let x_values = vec![1.0, 2.0, 4.0, 5.0];
|
||||
|
@ -297,7 +285,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_colormaps_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This header demos how to select colormaps."));
|
||||
ui.text("This header demos how to select colormaps.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
|
||||
// Select a colormap from the presets. The presets are listed in the Colormap enum
|
||||
|
@ -311,9 +299,7 @@ impl LinePlotDemoState {
|
|||
.build(plot_ui, || {
|
||||
(1..10)
|
||||
.map(|x| x as f64 * 0.1)
|
||||
.map(|x| {
|
||||
PlotLine::new(&format!("{:3.3}", x)).plot(&vec![0.1, 0.9], &vec![x, x])
|
||||
})
|
||||
.map(|x| PlotLine::new(&format!("{:3.3}", x)).plot(&[0.1, 0.9], &[x, x]))
|
||||
.count();
|
||||
});
|
||||
|
||||
|
@ -340,9 +326,7 @@ impl LinePlotDemoState {
|
|||
.build(plot_ui, || {
|
||||
(1..10)
|
||||
.map(|x| x as f64 * 0.1)
|
||||
.map(|x| {
|
||||
PlotLine::new(&format!("{:3.3}", x)).plot(&vec![0.1, 0.9], &vec![x, x])
|
||||
})
|
||||
.map(|x| PlotLine::new(&format!("{:3.3}", x)).plot(&[0.1, 0.9], &[x, x]))
|
||||
.count();
|
||||
});
|
||||
|
||||
|
@ -352,9 +336,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_conversions_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header demonstrates (in code) how to convert various ranges into ImRange"
|
||||
));
|
||||
ui.text("This header demonstrates (in code) how to convert various ranges into ImRange");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Simple line plot, conversion 1")
|
||||
.size([content_width, 300.0])
|
||||
|
@ -369,9 +351,7 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_linked_x_axis_plots(&mut self, ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"These plots have their X axes linked, but not the Y axes"
|
||||
));
|
||||
ui.text("These plots have their X axes linked, but not the Y axes");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Linked plot 1")
|
||||
.size([content_width, 300.0])
|
||||
|
@ -392,32 +372,38 @@ impl LinePlotDemoState {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(&mut self, ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Line plot: Basic")).build(&ui) {
|
||||
Self::show_basic_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Basic").build(ui) {
|
||||
Self::show_basic_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Configured")).build(&ui) {
|
||||
Self::show_configurable_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Configured").build(ui) {
|
||||
Self::show_configurable_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line Plot: Plot queries")).build(&ui) {
|
||||
Self::show_query_features_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line Plot: Plot queries").build(ui) {
|
||||
Self::show_query_features_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Plot styling")).build(&ui) {
|
||||
Self::show_style_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Plot styling").build(ui) {
|
||||
Self::show_style_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Colormaps")).build(&ui) {
|
||||
Self::show_colormaps_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Colormaps").build(ui) {
|
||||
Self::show_colormaps_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Multiple Y Axes")).build(&ui) {
|
||||
Self::show_two_yaxis_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Multiple Y Axes").build(ui) {
|
||||
Self::show_two_yaxis_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: \"Axis equal\"")).build(&ui) {
|
||||
Self::show_axis_equal_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: \"Axis equal\"").build(ui) {
|
||||
Self::show_axis_equal_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Range conversions")).build(&ui) {
|
||||
Self::show_conversions_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Range conversions").build(ui) {
|
||||
Self::show_conversions_plot(ui, plot_ui);
|
||||
}
|
||||
if CollapsingHeader::new(im_str!("Line plot: Linked plots")).build(&ui) {
|
||||
self.show_linked_x_axis_plots(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Line plot: Linked plots").build(ui) {
|
||||
self.show_linked_x_axis_plots(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LinePlotDemoState {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
//! This example demonstrates how scatter plots are to be used. For more general
|
||||
//! features of the libray, see the line_plots example.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{push_style_var_f32, push_style_var_i32, Marker, Plot, PlotScatter, PlotUi, StyleVar};
|
||||
|
||||
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header just draws a scatter plot with as little code as possible."
|
||||
));
|
||||
ui.text("This header just draws a scatter plot with as little code as possible.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Simple scatter plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -22,9 +20,7 @@ pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_custom_markers_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header shows how markers can be used in scatter plots."
|
||||
));
|
||||
ui.text("This header shows how markers can be used in scatter plots.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Multi-marker scatter plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -53,11 +49,11 @@ pub fn show_custom_markers_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Basic scatter plot")).build(&ui) {
|
||||
show_basic_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Basic scatter plot").build(ui) {
|
||||
show_basic_plot(ui, plot_ui);
|
||||
}
|
||||
|
||||
if CollapsingHeader::new(im_str!("Custom markers")).build(&ui) {
|
||||
show_custom_markers_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Custom markers").build(ui) {
|
||||
show_custom_markers_plot(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
//! This example demonstrates how stairs plots are to be used. They are almost the same as line
|
||||
//! plots, so head over to the line plots example for more info.
|
||||
//!
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{Plot, PlotStairs, PlotUi};
|
||||
|
||||
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text_wrapped(im_str!(
|
||||
"This header just plots a stairs-style line with as little code as possible."
|
||||
));
|
||||
ui.text_wrapped("This header just plots a stairs-style line with as little code as possible.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Simple stairs plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -22,7 +20,7 @@ pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Stairs plot: Basic")).build(&ui) {
|
||||
show_basic_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Stairs plot: Basic").build(ui) {
|
||||
show_basic_plot(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! This example demonstrates how stem plots are to be used. For more general
|
||||
//! features of the libray, see the line_plots example.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{Plot, PlotStems, PlotUi};
|
||||
|
||||
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!("This header shows a simple stem plot."));
|
||||
ui.text("This header shows a simple stem plot.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Stem plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -22,7 +22,7 @@ pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Stem plots")).build(&ui) {
|
||||
show_basic_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Stem plots").build(ui) {
|
||||
show_basic_plot(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
//! This example demonstrates how the text plotting features are to be used. For more general
|
||||
//! features of the libray, see the line_plots example.
|
||||
|
||||
use imgui::{im_str, CollapsingHeader, Ui};
|
||||
use imgui::{CollapsingHeader, Ui};
|
||||
use implot::{Plot, PlotText, PlotUi};
|
||||
|
||||
pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
||||
ui.text(im_str!(
|
||||
"This header just plots some text with as little code as possible."
|
||||
));
|
||||
ui.text("This header just plots some text with as little code as possible.");
|
||||
let content_width = ui.window_content_region_width();
|
||||
Plot::new("Simple text plot")
|
||||
// The size call could also be omitted, though the defaults don't consider window
|
||||
|
@ -29,7 +27,7 @@ pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) {
|
|||
}
|
||||
|
||||
pub fn show_demo_headers(ui: &Ui, plot_ui: &PlotUi) {
|
||||
if CollapsingHeader::new(im_str!("Text plot: Basic")).build(&ui) {
|
||||
show_basic_plot(&ui, &plot_ui);
|
||||
if CollapsingHeader::new("Text plot: Basic").build(ui) {
|
||||
show_basic_plot(ui, plot_ui);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use imgui::{im_str, Condition, Window};
|
||||
use imgui::{Condition, Window};
|
||||
use implot::Context;
|
||||
|
||||
// The actual backend-specific code is in this.
|
||||
|
@ -22,23 +22,20 @@ fn main() {
|
|||
demo_state.show_demos(ui, &plot_ui);
|
||||
}
|
||||
|
||||
Window::new(im_str!("Welcome to the ImPlot-rs demo!"))
|
||||
Window::new("Welcome to the ImPlot-rs demo!")
|
||||
.size([430.0, 450.0], Condition::FirstUseEver)
|
||||
.build(ui, || {
|
||||
ui.checkbox(im_str!("Show C++ ImPlot demo window"), &mut showing_demo);
|
||||
ui.checkbox(
|
||||
im_str!("Show Rust ImPlot demo windows"),
|
||||
&mut showing_rust_demo,
|
||||
);
|
||||
ui.checkbox("Show C++ ImPlot demo window", &mut showing_demo);
|
||||
ui.checkbox("Show Rust ImPlot demo windows", &mut showing_rust_demo);
|
||||
// TODO(4bb4) ... move windows by default so this is less confusing
|
||||
ui.text_wrapped(im_str!(
|
||||
ui.text_wrapped(
|
||||
"Note that the windows are stacked, so move this one out of the way to see\
|
||||
the ones beneath it. If you see something in the C++ demo window, but not\
|
||||
in the Rust ImPlot demo window, that means the bindings are likely not \
|
||||
implemented yet. Feel free to open an issue if you are missing something \
|
||||
in particular.
|
||||
"
|
||||
));
|
||||
",
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use imgui::{im_str, Condition, Window};
|
||||
use imgui::{Condition, Window};
|
||||
use implot::Context;
|
||||
|
||||
// The actual backend-specific code is in this.
|
||||
|
@ -22,23 +22,20 @@ fn main() {
|
|||
demo_state.show_demos(ui, &plot_ui);
|
||||
}
|
||||
|
||||
Window::new(im_str!("Welcome to the ImPlot-rs demo!"))
|
||||
Window::new("Welcome to the ImPlot-rs demo!")
|
||||
.size([430.0, 450.0], Condition::FirstUseEver)
|
||||
.build(ui, || {
|
||||
ui.checkbox(im_str!("Show C++ ImPlot demo window"), &mut showing_demo);
|
||||
ui.checkbox(
|
||||
im_str!("Show Rust ImPlot demo windows"),
|
||||
&mut showing_rust_demo,
|
||||
);
|
||||
ui.checkbox("Show C++ ImPlot demo window", &mut showing_demo);
|
||||
ui.checkbox("Show Rust ImPlot demo windows", &mut showing_rust_demo);
|
||||
// TODO(4bb4) ... move windows by default so this is less confusing
|
||||
ui.text_wrapped(im_str!(
|
||||
ui.text_wrapped(
|
||||
"Note that the windows are stacked, so move this one out of the way to see\
|
||||
the ones beneath it. If you see something in the C++ demo window, but not\
|
||||
in the Rust ImPlot demo window, that means the bindings are likely not \
|
||||
implemented yet. Feel free to open an issue if you are missing something \
|
||||
in particular.
|
||||
"
|
||||
));
|
||||
",
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
88
src/plot.rs
88
src/plot.rs
|
@ -5,10 +5,10 @@
|
|||
use crate::{Context, PlotLocation, PlotOrientation, PlotUi, YAxisChoice, NUMBER_OF_Y_AXES};
|
||||
use bitflags::bitflags;
|
||||
pub use imgui::Condition;
|
||||
use imgui::{im_str, ImString};
|
||||
use implot_sys as sys;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
pub use sys::{ImPlotLimits, ImPlotPoint, ImPlotRange, ImVec2, ImVec4};
|
||||
|
||||
const DEFAULT_PLOT_SIZE_X: f32 = 400.0;
|
||||
|
@ -105,17 +105,17 @@ enum AxisLimitSpecification {
|
|||
/// (If you are coming from the C++ implementation or the C bindings: build() calls both
|
||||
/// begin() and end() internally)
|
||||
pub struct Plot {
|
||||
/// Title of the plot, shown on top. Stored as ImString because that's what we'll use
|
||||
/// afterwards, and this ensures the ImString itself will stay alive long enough for the plot.
|
||||
title: ImString,
|
||||
/// Title of the plot, shown on top. Stored as CString because that's what we'll use
|
||||
/// afterwards, and this ensures the CString itself will stay alive long enough for the plot.
|
||||
title: CString,
|
||||
/// Size of the plot in [x, y] direction, in the same units imgui uses.
|
||||
size: [f32; 2],
|
||||
/// Label of the x axis, shown on the bottom. Stored as ImString because that's what we'll use
|
||||
/// afterwards, and this ensures the ImString itself will stay alive long enough for the plot.
|
||||
x_label: ImString,
|
||||
/// Label of the y axis, shown on the left. Stored as ImString because that's what we'll use
|
||||
/// afterwards, and this ensures the ImString itself will stay alive long enough for the plot.
|
||||
y_label: ImString,
|
||||
/// Label of the x axis, shown on the bottom. Stored as CString because that's what we'll use
|
||||
/// afterwards, and this ensures the CString itself will stay alive long enough for the plot.
|
||||
x_label: CString,
|
||||
/// Label of the y axis, shown on the left. Stored as CString because that's what we'll use
|
||||
/// afterwards, and this ensures the CString itself will stay alive long enough for the plot.
|
||||
y_label: CString,
|
||||
/// X axis limits, if present
|
||||
x_limits: Option<AxisLimitSpecification>,
|
||||
/// Y axis limits, if present
|
||||
|
@ -125,10 +125,10 @@ pub struct Plot {
|
|||
/// Labels for custom X axis ticks, if any. I'd prefer to store these together
|
||||
/// with the positions in one vector of an algebraic data type, but this would mean extra
|
||||
/// copies when it comes time to draw the plot because the C++ library expects separate lists.
|
||||
/// The data is stored as ImStrings because those are null-terminated, and since we have to
|
||||
/// The data is stored as CStrings because those are null-terminated, and since we have to
|
||||
/// convert to null-terminated data anyway, we may as well do that directly instead of cloning
|
||||
/// Strings and converting them afterwards.
|
||||
x_tick_labels: Option<Vec<ImString>>,
|
||||
x_tick_labels: Option<Vec<CString>>,
|
||||
/// Whether to also show the default X ticks when showing custom ticks or not
|
||||
show_x_default_ticks: bool,
|
||||
/// Positions for custom Y axis ticks, if any
|
||||
|
@ -136,10 +136,10 @@ pub struct Plot {
|
|||
/// Labels for custom Y axis ticks, if any. I'd prefer to store these together
|
||||
/// with the positions in one vector of an algebraic data type, but this would mean extra
|
||||
/// copies when it comes time to draw the plot because the C++ library expects separate lists.
|
||||
/// The data is stored as ImStrings because those are null-terminated, and since we have to
|
||||
/// The data is stored as CStrings because those are null-terminated, and since we have to
|
||||
/// convert to null-terminated data anyway, we may as well do that directly instead of cloning
|
||||
/// Strings and converting them afterwards.
|
||||
y_tick_labels: [Option<Vec<ImString>>; NUMBER_OF_Y_AXES],
|
||||
y_tick_labels: [Option<Vec<CString>>; NUMBER_OF_Y_AXES],
|
||||
/// Whether to also show the default Y ticks when showing custom ticks or not
|
||||
show_y_default_ticks: [bool; NUMBER_OF_Y_AXES],
|
||||
/// Configuration for the legend, if specified. The tuple contains location, orientation
|
||||
|
@ -158,18 +158,23 @@ pub struct Plot {
|
|||
|
||||
impl Plot {
|
||||
/// Create a new plot with some defaults set. Does not draw anything yet.
|
||||
/// Note that this uses antialiasing by default, unlike the C++ API. If you are seeing artifacts or weird rendering, try disabling it.
|
||||
/// Note that this uses antialiasing by default, unlike the C++ API. If you are seeing
|
||||
/// artifacts or weird rendering, try disabling it.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the title string contains internal null bytes.
|
||||
pub fn new(title: &str) -> Self {
|
||||
// Needed for initialization, see https://github.com/rust-lang/rust/issues/49147
|
||||
const POS_NONE: Option<Vec<f64>> = None;
|
||||
const TICK_NONE: Option<Vec<ImString>> = None;
|
||||
const TICK_NONE: Option<Vec<CString>> = None;
|
||||
|
||||
// TODO(4bb4) question these defaults, maybe remove some of them
|
||||
Self {
|
||||
title: im_str!("{}", title),
|
||||
title: CString::new(title)
|
||||
.unwrap_or_else(|_| panic!("String contains internal null bytes: {}", title)),
|
||||
size: [DEFAULT_PLOT_SIZE_X, DEFAULT_PLOT_SIZE_Y],
|
||||
x_label: im_str!("").into(),
|
||||
y_label: im_str!("").into(),
|
||||
x_label: CString::new("").unwrap(),
|
||||
y_label: CString::new("").unwrap(),
|
||||
x_limits: None,
|
||||
y_limits: Default::default(),
|
||||
x_tick_positions: None,
|
||||
|
@ -194,16 +199,24 @@ impl Plot {
|
|||
}
|
||||
|
||||
/// Set the x label of the plot
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
#[inline]
|
||||
pub fn x_label(mut self, label: &str) -> Self {
|
||||
self.x_label = im_str!("{}", label);
|
||||
self.x_label = CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("String contains internal null bytes: {}", label));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the y label of the plot
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
#[inline]
|
||||
pub fn y_label(mut self, label: &str) -> Self {
|
||||
self.y_label = im_str!("{}", label);
|
||||
self.y_label = CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("String contains internal null bytes: {}", label));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -338,6 +351,9 @@ impl Plot {
|
|||
/// Set X ticks with labels for the plot. The vector contains one position and label
|
||||
/// each in the form of a tuple `(label_position, label_string)`. The `show_default`
|
||||
/// setting determines whether the default ticks are also shown.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if any of the tick label strings contain internal null bytes.
|
||||
#[inline]
|
||||
pub fn x_ticks_with_labels(
|
||||
mut self,
|
||||
|
@ -345,7 +361,15 @@ impl Plot {
|
|||
show_default: bool,
|
||||
) -> Self {
|
||||
self.x_tick_positions = Some(tick_labels.iter().map(|x| x.0).collect());
|
||||
self.x_tick_labels = Some(tick_labels.iter().map(|x| im_str!("{}", x.1)).collect());
|
||||
self.x_tick_labels = Some(
|
||||
tick_labels
|
||||
.iter()
|
||||
.map(|x| {
|
||||
CString::new(x.1.as_str())
|
||||
.unwrap_or_else(|_| panic!("String contains internal null bytes: {}", x.1))
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
self.show_x_default_ticks = show_default;
|
||||
self
|
||||
}
|
||||
|
@ -353,6 +377,9 @@ impl Plot {
|
|||
/// Set Y ticks with labels for the plot. The vector contains one position and label
|
||||
/// each in the form of a tuple `(label_position, label_string)`. The `show_default`
|
||||
/// setting determines whether the default ticks are also shown.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if any of the tick label strings contain internal null bytes.
|
||||
#[inline]
|
||||
pub fn y_ticks_with_labels(
|
||||
mut self,
|
||||
|
@ -362,8 +389,15 @@ impl Plot {
|
|||
) -> Self {
|
||||
let axis_index = y_axis_choice as usize;
|
||||
self.y_tick_positions[axis_index] = Some(tick_labels.iter().map(|x| x.0).collect());
|
||||
self.y_tick_labels[axis_index] =
|
||||
Some(tick_labels.iter().map(|x| im_str!("{}", x.1)).collect());
|
||||
self.y_tick_labels[axis_index] = Some(
|
||||
tick_labels
|
||||
.iter()
|
||||
.map(|x| {
|
||||
CString::new(x.1.as_str())
|
||||
.unwrap_or_else(|_| panic!("String contains internal null bytes: {}", x.1))
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
self.show_y_default_ticks[axis_index] = show_default;
|
||||
self
|
||||
}
|
||||
|
@ -618,7 +652,7 @@ impl Plot {
|
|||
pub struct PlotToken {
|
||||
context: *const Context,
|
||||
/// For better error messages
|
||||
plot_title: ImString,
|
||||
plot_title: CString,
|
||||
}
|
||||
|
||||
impl PlotToken {
|
||||
|
@ -634,7 +668,7 @@ impl Drop for PlotToken {
|
|||
fn drop(&mut self) {
|
||||
if !self.context.is_null() && !std::thread::panicking() {
|
||||
panic!(
|
||||
"Warning: A PlotToken for plot \"{}\" was not called end() on",
|
||||
"Warning: A PlotToken for plot \"{:?}\" was not called end() on",
|
||||
self.plot_title
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//! as lines, bars, scatter plots and text in a plot. For the module to create plots themselves,
|
||||
//! see `plot`.
|
||||
use crate::sys;
|
||||
use imgui::{im_str, ImString};
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
pub use crate::sys::ImPlotPoint;
|
||||
|
@ -13,14 +13,18 @@ pub use crate::sys::ImPlotPoint;
|
|||
/// Struct to provide functionality for plotting a line in a plot.
|
||||
pub struct PlotLine {
|
||||
/// Label to show in the legend for this line
|
||||
label: String,
|
||||
label: CString,
|
||||
}
|
||||
|
||||
impl PlotLine {
|
||||
/// Create a new line to be plotted. Does not draw anything yet.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +36,7 @@ impl PlotLine {
|
|||
}
|
||||
unsafe {
|
||||
sys::ImPlot_PlotLinedoublePtrdoublePtr(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
y.as_ptr(),
|
||||
x.len().min(y.len()) as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
|
||||
|
@ -46,14 +50,18 @@ impl PlotLine {
|
|||
/// Struct to provide functionality for plotting a line in a plot with stairs style.
|
||||
pub struct PlotStairs {
|
||||
/// Label to show in the legend for this line
|
||||
label: String,
|
||||
label: CString,
|
||||
}
|
||||
|
||||
impl PlotStairs {
|
||||
/// Create a new line to be plotted. Does not draw anything yet.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +74,7 @@ impl PlotStairs {
|
|||
}
|
||||
unsafe {
|
||||
sys::ImPlot_PlotStairsdoublePtrdoublePtr(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
y.as_ptr(),
|
||||
x.len().min(y.len()) as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
|
||||
|
@ -80,14 +88,18 @@ impl PlotStairs {
|
|||
/// Struct to provide functionality for creating a scatter plot
|
||||
pub struct PlotScatter {
|
||||
/// Label to show in the legend for this scatter plot
|
||||
label: String,
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
label: CString,
|
||||
}
|
||||
|
||||
impl PlotScatter {
|
||||
/// Create a new scatter plot to be shown. Does not draw anything yet.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +112,7 @@ impl PlotScatter {
|
|||
}
|
||||
unsafe {
|
||||
sys::ImPlot_PlotScatterdoublePtrdoublePtr(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
y.as_ptr(),
|
||||
x.len().min(y.len()) as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
|
||||
|
@ -114,7 +126,7 @@ impl PlotScatter {
|
|||
/// Struct to provide bar plotting functionality.
|
||||
pub struct PlotBars {
|
||||
/// Label to show in the legend for this line
|
||||
label: String,
|
||||
label: CString,
|
||||
|
||||
/// Width of the bars, in plot coordinate terms
|
||||
bar_width: f64,
|
||||
|
@ -126,9 +138,13 @@ pub struct PlotBars {
|
|||
impl PlotBars {
|
||||
/// Create a new bar plot to be shown. Defaults to drawing vertical bars.
|
||||
/// Does not draw anything yet.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
bar_width: 0.67, // Default value taken from C++ implot
|
||||
horizontal_bars: false,
|
||||
}
|
||||
|
@ -164,18 +180,34 @@ impl PlotBars {
|
|||
let (plot_function, x, y);
|
||||
if self.horizontal_bars {
|
||||
plot_function = sys::ImPlot_PlotBarsHdoublePtrdoublePtr
|
||||
as unsafe extern "C" fn(*const c_char, *const f64, *const f64, i32, f64, i32, i32);
|
||||
as unsafe extern "C" fn(
|
||||
*const c_char,
|
||||
*const f64,
|
||||
*const f64,
|
||||
i32,
|
||||
f64,
|
||||
i32,
|
||||
i32,
|
||||
);
|
||||
x = bar_values;
|
||||
y = axis_positions;
|
||||
} else {
|
||||
plot_function = sys::ImPlot_PlotBarsdoublePtrdoublePtr
|
||||
as unsafe extern "C" fn(*const c_char, *const f64, *const f64, i32, f64, i32, i32);
|
||||
as unsafe extern "C" fn(
|
||||
*const c_char,
|
||||
*const f64,
|
||||
*const f64,
|
||||
i32,
|
||||
f64,
|
||||
i32,
|
||||
i32,
|
||||
);
|
||||
x = axis_positions;
|
||||
y = bar_values;
|
||||
};
|
||||
|
||||
plot_function(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x.as_ptr(),
|
||||
y.as_ptr(),
|
||||
number_of_points as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
|
||||
|
@ -190,7 +222,7 @@ impl PlotBars {
|
|||
/// Struct to provide functionality for adding text within a plot
|
||||
pub struct PlotText {
|
||||
/// Label to show in plot
|
||||
label: String,
|
||||
label: CString,
|
||||
|
||||
/// X component of the pixel offset to be used. Will be used independently of the actual plot
|
||||
/// scaling. Defaults to 0.
|
||||
|
@ -203,9 +235,13 @@ pub struct PlotText {
|
|||
|
||||
impl PlotText {
|
||||
/// Create a new text label to be shown. Does not draw anything yet.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label string contains internal null bytes.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.into(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
pixel_offset_x: 0.0,
|
||||
pixel_offset_y: 0.0,
|
||||
}
|
||||
|
@ -223,13 +259,13 @@ impl PlotText {
|
|||
/// closures passed to [`Plot::build()`](struct.Plot.html#method.build)
|
||||
pub fn plot(&self, x: f64, y: f64, vertical: bool) {
|
||||
// If there is nothing to show, don't do anything
|
||||
if self.label.is_empty() {
|
||||
if self.label.as_bytes().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
sys::ImPlot_PlotText(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
x,
|
||||
y,
|
||||
vertical,
|
||||
|
@ -245,7 +281,7 @@ impl PlotText {
|
|||
/// Struct to provide functionality for creating headmaps.
|
||||
pub struct PlotHeatmap {
|
||||
/// Label to show in plot
|
||||
label: String,
|
||||
label: CString,
|
||||
|
||||
/// Scale range of the values shown. If this is set to `None`, the scale
|
||||
/// is computed based on the values given to the `plot` function. If there
|
||||
|
@ -255,7 +291,7 @@ pub struct PlotHeatmap {
|
|||
/// Label C style format string, this is shown when a a value point is hovered.
|
||||
/// None means don't show a label. The label is stored directly as an ImString because
|
||||
/// that is what's needed for the plot call anyway. Conversion is done in the setter.
|
||||
label_format: Option<ImString>,
|
||||
label_format: Option<CString>,
|
||||
|
||||
/// Lower left point for the bounding rectangle. This is called `bounds_min` in the C++ code.
|
||||
drawarea_lower_left: ImPlotPoint,
|
||||
|
@ -271,9 +307,10 @@ impl PlotHeatmap {
|
|||
/// anything yet.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
scale_range: None,
|
||||
label_format: Some(im_str!("%.1f").to_owned()),
|
||||
label_format: Some(CString::new("%.1f").unwrap()),
|
||||
drawarea_lower_left: ImPlotPoint { x: 0.0, y: 0.0 },
|
||||
drawarea_upper_right: ImPlotPoint { x: 1.0, y: 1.0 },
|
||||
}
|
||||
|
@ -286,8 +323,14 @@ impl PlotHeatmap {
|
|||
}
|
||||
|
||||
/// Specify the label format for hovered data points.. `None` means no label is shown.
|
||||
///
|
||||
/// # Panics
|
||||
/// Will panic if the label format string contains internal null bytes.
|
||||
pub fn with_label_format(mut self, label_format: Option<&str>) -> Self {
|
||||
self.label_format = label_format.map(|x| im_str!("{}", x));
|
||||
self.label_format = label_format.map(|x| {
|
||||
CString::new(x)
|
||||
.unwrap_or_else(|_| panic!("Format label string has internal null bytes: {}", x))
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -314,7 +357,7 @@ impl PlotHeatmap {
|
|||
|
||||
unsafe {
|
||||
sys::ImPlot_PlotHeatmapdoublePtr(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
values.as_ptr(),
|
||||
number_of_rows as i32, // Not sure why C++ code uses a signed value here
|
||||
number_of_cols as i32, // Not sure why C++ code uses a signed value here
|
||||
|
@ -337,7 +380,7 @@ impl PlotHeatmap {
|
|||
/// Struct to provide stem plotting functionality.
|
||||
pub struct PlotStems {
|
||||
/// Label to show in the legend for this line
|
||||
label: String,
|
||||
label: CString,
|
||||
|
||||
/// Reference value for the y value, which the stems are "with respect to"
|
||||
reference_y: f64,
|
||||
|
@ -348,7 +391,8 @@ impl PlotStems {
|
|||
/// [`PlotStems::plot`] on the struct for that.
|
||||
pub fn new(label: &str) -> Self {
|
||||
Self {
|
||||
label: label.to_owned(),
|
||||
label: CString::new(label)
|
||||
.unwrap_or_else(|_| panic!("Label string has internal null bytes: {}", label)),
|
||||
reference_y: 0.0, // Default value taken from C++ implot
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +414,7 @@ impl PlotStems {
|
|||
}
|
||||
unsafe {
|
||||
sys::ImPlot_PlotStemsdoublePtrdoublePtr(
|
||||
im_str!("{}", self.label).as_ptr() as *const c_char,
|
||||
self.label.as_ptr() as *const c_char,
|
||||
axis_positions.as_ptr(),
|
||||
stem_values.as_ptr(),
|
||||
number_of_points as i32, // "as" casts saturate as of Rust 1.45. This is safe here.
|
||||
|
|
Loading…
Reference in a new issue