From 4645414624185e650f068b5b2dc85d1f41b0dd6d Mon Sep 17 00:00:00 2001 From: 4bb4 <67376761+4bb4@users.noreply.github.com> Date: Sat, 31 Oct 2020 12:05:57 +0100 Subject: [PATCH] Added legend location setting --- README.md | 7 ++-- .../examples-shared/src/line_plots.rs | 7 ++-- src/lib.rs | 42 ++++++++++++++++--- src/plot.rs | 38 ++++++++++++++++- 4 files changed, 82 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9ec70f0..1f3520e 100644 --- a/README.md +++ b/README.md @@ -74,13 +74,13 @@ created for 64-bit floats. - [ ] Annotations - [ ] Dragline - [ ] Dragpoint -- [ ] Plot customization +- [x] Plot customization - [x] Axis flags - [x] Styling colors - [x] Styling variables - [x] Colormaps - - [ ] Legend locations -- [x] Plot querying + - [x] Legend locations +- [ ] Plot querying - [x] is hovered - [x] mouse position in plot - [x] plot limits @@ -88,6 +88,7 @@ created for 64-bit floats. - [x] get plot query - [x] are axes hovered - [x] Choice of y axis + - [ ] Are legend entries hovered - [ ] Utils - [x] Plot limit setting - [x] imgui-rs style safe push/pop stacks diff --git a/implot-examples/examples-shared/src/line_plots.rs b/implot-examples/examples-shared/src/line_plots.rs index 82c1cb7..b2fb3d3 100644 --- a/implot-examples/examples-shared/src/line_plots.rs +++ b/implot-examples/examples-shared/src/line_plots.rs @@ -6,8 +6,8 @@ use implot::{ get_plot_limits, get_plot_mouse_position, get_plot_query, is_plot_hovered, is_plot_queried, push_style_color, push_style_var_f32, push_style_var_i32, set_colormap_from_preset, set_colormap_from_vec, set_plot_y_axis, AxisFlags, Colormap, ImPlotLimits, ImPlotPoint, - ImPlotRange, ImVec4, Marker, Plot, PlotColorElement, PlotFlags, PlotLine, PlotUi, StyleVar, - YAxisChoice, + ImPlotRange, ImVec4, Marker, Plot, PlotColorElement, PlotFlags, PlotLine, PlotLocation, + PlotOrientation, PlotUi, StyleVar, YAxisChoice, }; pub fn show_basic_plot(ui: &Ui, plot_ui: &PlotUi) { @@ -121,8 +121,9 @@ pub fn show_configurable_plot(ui: &Ui, plot_ui: &PlotUi) { .with_plot_flags(&plot_flags) .with_x_axis_flags(&x_axis_flags) .with_y_axis_flags(YAxisChoice::First, &y_axis_flags) + .with_legend_location(&PlotLocation::West, &PlotOrientation::Horizontal, true) .build(plot_ui, || { - PlotLine::new("A line").plot(&vec![2.1, 2.9], &vec![1.1, 1.9]); + PlotLine::new("A line 2").plot(&vec![2.4, 2.9], &vec![1.1, 1.9]); }); } diff --git a/src/lib.rs b/src/lib.rs index d6d297c..e47954c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,11 +37,11 @@ const NUMBER_OF_Y_AXES: usize = 3; // so we can store data about individual axes in arrays, so this pretty much should stay // just a mapping of words to numbers. #[derive(Clone)] -#[repr(i32)] +#[repr(u32)] pub enum YAxisChoice { - First = 0, - Second = 1, - Third = 2, + First = sys::ImPlotYAxis__ImPlotYAxis_1, + Second = sys::ImPlotYAxis__ImPlotYAxis_2, + Third = sys::ImPlotYAxis__ImPlotYAxis_3, } /// A temporary reference for building plots. This does not really do anything on its own at @@ -51,7 +51,7 @@ pub struct PlotUi<'ui> { context: &'ui Context, } -// --- Markers, color maps, style variables---------------------------------------------------- +// --- Markers, color maps, style variables, legend location ---------------------------------- /// Markers, documentation copied from implot.h for convenience. #[repr(i32)] #[derive(Copy, Clone, Debug)] @@ -221,6 +221,38 @@ pub enum StyleVar { PlotMinSize = sys::ImPlotStyleVar__ImPlotStyleVar_PlotMinSize, } +/// Used to position items on a plot (e.g. legends, labels, etc.) +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum PlotLocation { + /// Center-center + Center = sys::ImPlotLocation__ImPlotLocation_Center, + /// Top-center + North = sys::ImPlotLocation__ImPlotLocation_North, + /// Bottom-center + South = sys::ImPlotLocation__ImPlotLocation_South, + /// Center-left + West = sys::ImPlotLocation__ImPlotLocation_West, + /// Center-right + East = sys::ImPlotLocation__ImPlotLocation_East, + /// Top-left + NorthWest = sys::ImPlotLocation__ImPlotLocation_NorthWest, + /// Top-right + NorthEast = sys::ImPlotLocation__ImPlotLocation_NorthEast, + /// Bottom-left + SouthWest = sys::ImPlotLocation__ImPlotLocation_SouthWest, + /// Bottom-right + SouthEast = sys::ImPlotLocation__ImPlotLocation_SouthEast, +} + +/// Used to orient items on a plot (e.g. legends, labels, etc.) +#[repr(u32)] +#[derive(Copy, Clone, Debug)] +pub enum PlotOrientation { + Horizontal = sys::ImPlotOrientation__ImPlotOrientation_Horizontal, + Vertical = sys::ImPlotOrientation__ImPlotOrientation_Vertical, +} + /// Switch to one of the built-in preset colormaps. If samples is greater than 1, the map will be /// linearly resampled. pub fn set_colormap_from_preset(preset: Colormap, samples: u32) { diff --git a/src/plot.rs b/src/plot.rs index 34319c6..e182cd4 100644 --- a/src/plot.rs +++ b/src/plot.rs @@ -2,7 +2,7 @@ //! //! This module defines the `Plot` struct, which is used to create a 2D plot that will //! contain all other objects that can be created using this library. -use crate::{Context, PlotUi, YAxisChoice, NUMBER_OF_Y_AXES}; +use crate::{Context, PlotLocation, PlotOrientation, PlotUi, YAxisChoice, NUMBER_OF_Y_AXES}; use bitflags::bitflags; pub use imgui::Condition; use imgui::{im_str, ImString}; @@ -133,6 +133,12 @@ pub struct Plot { y_tick_labels: [Option>; 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], + /// Orientation of the legend + legend_orientation: PlotOrientation, + /// Location of the legend + legend_location: PlotLocation, + /// Whether the legend is shown outside the plot + legend_outside_plot: bool, /// Flags relating to the plot TODO(4bb4) make those into bitflags plot_flags: sys::ImPlotFlags, /// Flags relating to the X axis of the plot TODO(4bb4) make those into bitflags @@ -166,6 +172,9 @@ impl Plot { y_tick_positions: [POS_NONE; NUMBER_OF_Y_AXES], y_tick_labels: [TICK_NONE; NUMBER_OF_Y_AXES], show_y_default_ticks: [false; NUMBER_OF_Y_AXES], + legend_location: PlotLocation::NorthWest, + legend_orientation: PlotOrientation::Vertical, + legend_outside_plot: false, plot_flags: PlotFlags::ANTIALIASED.bits() as sys::ImPlotFlags, x_flags: AxisFlags::NONE.bits() as sys::ImPlotAxisFlags, y_flags: [AxisFlags::NONE.bits() as sys::ImPlotAxisFlags; NUMBER_OF_Y_AXES], @@ -299,6 +308,20 @@ impl Plot { self } + /// Set the legend location, orientation and whether it is to be drawn outside the plot + #[inline] + pub fn with_legend_location( + mut self, + location: &PlotLocation, + orientation: &PlotOrientation, + outside: bool, + ) -> Self { + self.legend_location = *location; + self.legend_orientation = *orientation; + self.legend_outside_plot = outside; + self + } + /// Internal helper function to set axis limits in case they are specified. fn maybe_set_axis_limits(&self) { // Set X limits if specified @@ -415,6 +438,19 @@ impl Plot { }; if should_render { + // Configure legend location. This has to be called between begin() and end(), + // but since only the last call to it actually affects the outcome, I'm adding + // it here instead of as a freestanding function. If this is too restrictive + // (for example, if you want to set the location based on code running _during_ + // the plotting for some reason), file an issue and we'll move it. + unsafe { + sys::ImPlot_SetLegendLocation( + self.legend_location as i32, + self.legend_orientation as i32, + self.legend_outside_plot, + ) + } + Some(PlotToken { context: plot_ui.context, plot_title: self.title.clone(),