Button support and FieldSetter derive macro #99
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Thank you for this wonderful crate. I have personally found it much easier to make a plotly chart using this crate aided by the Rust type system as opposed to other options. Excited to contribute to this repository.
This PR introduces two changes:
Change 1: FieldSetter derive marco
There are a number of structs defined in this crate that have private fields and public functions to set the value for each of these fields. The
FieldSetter
procedural marco, when applied on a struct, auto-derives the public setter functions for each of the fields in the struct. The setter functions have a small number of distinct signatures based on the type of the field. Types such asDim, String, Color, NumOrString
get a special syntax. The procedural macro is defined in theplotly_derive
crate. I have updated thetraces
andlayout
modules to use the procedural macro (resulting in a lot of code deletions). The macro also proved two attributes#[field_setter(box_self)]
- The setter functions returnBox<Self>
instead ofSelf
if applied to the struct#[field_setter(skip)]
- To skip generating setter function for a specific fieldThe procedural macro is not fully general to cover type aliasing etc, but works in practice for this crate.
Pros
Cons
Change 2: Support for Buttons (update menu)
I have defined the structs required to support buttons in a plotly chart (https://plotly.com/javascript/reference/layout/updatemenus/) in a new module
layout/update_menu.rs
.Using these structs we can add buttons with this crate. However the button API (https://plotly.com/python/dropdowns/) is not strongly-typed and needs lots of "stringy" arguments. Instead, I have added a new approach to help create buttons. There are three button methods that I have focused on:
restyle
: modify tracesrelayout
: modify layoutupdate
modify traces and layoutRestyles
First I have defined a
Restyle
marker trait. TheFieldSetter
macro defines a new enum for each struct if it is marked as#[field_setter(kind = "trace")]
. As an example, say we are deriving FieldSetter on the (simplified)SimpleBar
structThe derived enum would look like
i.e it contains one enum variant for modifying each of the struct fields. The reason each field is wrapped with a
Dim
is that plotly provide option to modify all the traces in the plot using a scalar argument or control what to modify in each trace using a list argument. This enum implements theRestyle
trait.Additionally we also define helper functions for SimpleBar
Coupled with this we have a
ButtonBuilder
struct that has apush_restyle()
function which accepts any struct that implementsRestyle
trait. On invoking theButtonBuilder::build()
function, the builder sets up the Button correctly with the arguments in the right form.So for example, if we have two bar plots and we want a button to alternate between them, we can create the button using
Relayout
Similar to
Restyle
we have aRelayout
trait. We derive a new enum which implementsRelayout
if the struct is annotated with#[field_setter(kind = "layout")]
. Since you only have a single layout per plot, we don't do theDim
wrapping here. TheButtonBuilder
also has apush_relayout
function.Examples
Three plots that demonstrate the use of
UpdateMenu
to create buttons:Dropdown to alternate between two bar plots (restyle)

Heatmap with buttons to choose colorscale (restyle)

Button to change barmode (relayout)
