diff --git a/CHANGELOG.md b/CHANGELOG.md
index eab1cfc5..0aefb75a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
- [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`.
- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter.
- [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`.
+- [[#157](https://github.com/plotly/plotly.rs/pull/157)] Fix `HeatMap`'s setters for correctly setting `zmin`, `zmax` and `zmin` independent of `Z` input type.
+- [[#154](https://github.com/plotly/plotly.rs/pull/154)] Improve ergonomics of `Title` and `LegendGroupTitle` structs: `new` method now takes no arguments as per other structs, whilst a new `with_text()` constructor is added for convenience. Where other structs contain a `Title` (and `LegendGroupTitle`), users can now call the `title()` (and `legend_group_title()`) method with anything that `impl`s `Into
`, viz. `String`, `&String`, `&str` and `Title`.
- [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`.
## [0.8.4] - 2023-07-09
diff --git a/examples/3d_charts/src/main.rs b/examples/3d_charts/src/main.rs
index e575daf1..ed484f73 100644
--- a/examples/3d_charts/src/main.rs
+++ b/examples/3d_charts/src/main.rs
@@ -3,7 +3,7 @@
use ndarray::Array;
use plotly::{
color::Rgb,
- common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode, Title},
+ common::{ColorBar, ColorScale, ColorScalePalette, Font, Marker, MarkerSymbol, Mode},
layout::{Axis, Camera, Layout, LayoutScene, Legend, Margin, ProjectionType},
Mesh3D, Plot, Scatter3D, Surface,
};
@@ -69,7 +69,7 @@ fn customized_scatter3d_plot() {
let front_color: Rgb = Rgb::new(255, 255, 255);
let layout = Layout::new()
- .title("Helix".into())
+ .title("Helix")
.legend(Legend::new().x(0.9).y(0.9))
.font(Font::new().color(front_color))
.paper_background_color(background_color)
@@ -77,19 +77,19 @@ fn customized_scatter3d_plot() {
LayoutScene::new()
.x_axis(
Axis::new()
- .title("x (A meaningful axis name goes here)".into())
+ .title("x (A meaningful axis name goes here)")
.tick_angle(0f64)
.grid_color(front_color)
.color(front_color),
)
.y_axis(
Axis::new()
- .title(Title::new("This is the label of the Y axis"))
+ .title("This is the label of the Y axis")
.tick_format(".1f")
.grid_color(front_color)
.color(front_color),
)
- .z_axis(Axis::new().title("".into()).tick_values(vec![]))
+ .z_axis(Axis::new().title("").tick_values(vec![]))
.aspect_mode(plotly::layout::AspectMode::Manual)
.aspect_ratio((3.0, 1.0, 1.0).into())
.camera(
@@ -213,7 +213,7 @@ fn colorscale_plot() {
let layout = Layout::new()
.font(Font::new().size(18).family("Palatino-Linotype"))
- .title(format!("Colorscale: {colorscale:?}").as_str().into())
+ .title(format!("Colorscale: {colorscale:?}"))
.width(1200)
.height(1000)
.scene(
diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs
index 9408c755..14f31adb 100644
--- a/examples/basic_charts/src/main.rs
+++ b/examples/basic_charts/src/main.rs
@@ -5,7 +5,7 @@ use plotly::{
color::{NamedColor, Rgb, Rgba},
common::{
ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode,
- Orientation, Title,
+ Orientation,
},
layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder},
sankey::{Line as SankeyLine, Link, Node},
@@ -118,9 +118,9 @@ fn data_labels_hover() {
plot.add_trace(trace2);
let layout = Layout::new()
- .title("Data Labels Hover".into())
- .x_axis(Axis::new().title("x".into()).range(vec![0.75, 5.25]))
- .y_axis(Axis::new().title("y".into()).range(vec![0., 8.]));
+ .title("Data Labels Hover")
+ .x_axis(Axis::new().title("x").range(vec![0.75, 5.25]))
+ .y_axis(Axis::new().title("y").range(vec![0., 8.]));
plot.set_layout(layout);
plot.show();
@@ -143,7 +143,7 @@ fn data_labels_on_the_plot() {
plot.add_trace(trace2);
let layout = Layout::new()
- .title("Data Labels on the Plot".into())
+ .title("Data Labels on the Plot")
.x_axis(Axis::new().range(vec![0.75, 5.25]))
.y_axis(Axis::new().range(vec![0., 8.]));
plot.set_layout(layout);
@@ -216,14 +216,14 @@ fn colored_and_styled_scatter_plot() {
.marker(Marker::new().color(Rgb::new(142, 124, 195)).size(12));
let layout = Layout::new()
- .title(Title::new("Quarter 1 Growth"))
+ .title("Quarter 1 Growth")
.x_axis(
Axis::new()
- .title(Title::new("GDP per Capita"))
+ .title("GDP per Capita")
.show_grid(false)
.zero_line(false),
)
- .y_axis(Axis::new().title(Title::new("Percent")).show_line(false));
+ .y_axis(Axis::new().title("Percent").show_line(false));
let mut plot = Plot::new();
plot.add_trace(trace1);
plot.add_trace(trace2);
@@ -280,7 +280,7 @@ fn adding_names_to_line_and_scatter_plot() {
.mode(Mode::LinesMarkers)
.name("Scatter + Lines");
- let layout = Layout::new().title(Title::new("Adding Names to Line and Scatter Plot"));
+ let layout = Layout::new().title("Adding Names to Line and Scatter Plot");
let mut plot = Plot::new();
plot.add_trace(trace1);
plot.add_trace(trace2);
@@ -305,7 +305,7 @@ fn line_and_scatter_styling() {
.marker(Marker::new().color(Rgb::new(128, 0, 128)).size(12))
.line(Line::new().color(Rgb::new(128, 0, 128)).width(1.0));
- let layout = Layout::new().title(Title::new("Line and Scatter Styling"));
+ let layout = Layout::new().title("Line and Scatter Styling");
let mut plot = Plot::new();
plot.add_trace(trace1);
plot.add_trace(trace2);
@@ -326,7 +326,7 @@ fn styling_line_plot() {
.line(Line::new().color(Rgb::new(55, 128, 191)).width(1.0));
let layout = Layout::new()
- .title(Title::new("Styling Line Plot"))
+ .title("Styling Line Plot")
.width(500)
.height(500);
let mut plot = Plot::new();
@@ -595,7 +595,7 @@ fn basic_sankey_diagram() {
);
let layout = Layout::new()
- .title("Basic Sankey".into())
+ .title("Basic Sankey")
.font(Font::new().size(10));
let mut plot = Plot::new();
diff --git a/examples/financial_charts/src/main.rs b/examples/financial_charts/src/main.rs
index 2805482b..1473699e 100644
--- a/examples/financial_charts/src/main.rs
+++ b/examples/financial_charts/src/main.rs
@@ -3,7 +3,7 @@
use std::env;
use std::path::PathBuf;
-use plotly::common::{TickFormatStop, Title};
+use plotly::common::TickFormatStop;
use plotly::layout::{Axis, RangeSelector, RangeSlider, SelectorButton, SelectorStep, StepMode};
use plotly::{Candlestick, Layout, Ohlc, Plot, Scatter};
use serde::Deserialize;
@@ -50,7 +50,7 @@ fn time_series_plot_with_custom_date_range() {
let layout = Layout::new()
.x_axis(Axis::new().range(vec!["2016-07-01", "2016-12-31"]))
- .title(Title::new("Manually Set Date Range"));
+ .title("Manually Set Date Range");
plot.set_layout(layout);
plot.show();
@@ -68,7 +68,7 @@ fn time_series_with_range_slider() {
let layout = Layout::new()
.x_axis(Axis::new().range_slider(RangeSlider::new().visible(true)))
- .title(Title::new("Manually Set Date Range"));
+ .title("Manually Set Date Range");
plot.set_layout(layout);
plot.show();
diff --git a/examples/scientific_charts/src/main.rs b/examples/scientific_charts/src/main.rs
index 34ace161..bea229e2 100644
--- a/examples/scientific_charts/src/main.rs
+++ b/examples/scientific_charts/src/main.rs
@@ -2,7 +2,7 @@
use std::f64::consts::PI;
-use plotly::common::{ColorScale, ColorScalePalette, Font, Title};
+use plotly::common::{ColorScale, ColorScalePalette, Font};
use plotly::contour::Contours;
use plotly::{Contour, HeatMap, Layout, Plot};
@@ -47,7 +47,7 @@ fn colorscale_for_contour_plot() {
];
let trace = Contour::new_z(z).color_scale(ColorScale::Palette(ColorScalePalette::Jet));
- let layout = Layout::new().title(Title::new("Colorscale for Contour Plot"));
+ let layout = Layout::new().title("Colorscale for Contour Plot");
let mut plot = Plot::new();
plot.set_layout(layout);
plot.add_trace(trace);
@@ -68,7 +68,7 @@ fn customizing_size_and_range_of_a_contour_plots_contours() {
.auto_contour(false)
.contours(Contours::new().start(0.0).end(8.0).size(2));
- let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours"));
+ let layout = Layout::new().title("Customizing Size and Range of Contours");
let mut plot = Plot::new();
plot.set_layout(layout);
plot.add_trace(trace);
@@ -91,7 +91,7 @@ fn customizing_spacing_between_x_and_y_ticks() {
.dy(10.0)
.y0(10.0);
- let layout = Layout::new().title(Title::new("Customizing Size and Range of Contours"));
+ let layout = Layout::new().title("Customizing Size and Range of Contours");
let mut plot = Plot::new();
plot.set_layout(layout);
plot.add_trace(trace);
@@ -136,7 +136,7 @@ fn customized_heat_map() {
.color_scale(colorscale.into());
let layout = Layout::new()
- .title(Title::new("Customized Heatmap"))
+ .title("Customized Heatmap")
.font(Font::new().size(32));
let mut plot = Plot::new();
diff --git a/examples/shapes/src/main.rs b/examples/shapes/src/main.rs
index 871986d1..84eaafc0 100644
--- a/examples/shapes/src/main.rs
+++ b/examples/shapes/src/main.rs
@@ -138,7 +138,7 @@ fn creating_tangent_lines_with_shapes() {
plot.add_trace(trace);
let mut layout =
- Layout::new().title("$f(x)=x\\sin(x^2)+1\\\\ f\'(x)=\\sin(x^2)+2x^2\\cos(x^2)$".into());
+ Layout::new().title("$f(x)=x\\sin(x^2)+1\\\\ f\'(x)=\\sin(x^2)+2x^2\\cos(x^2)$");
layout.add_shape(
Shape::new()
diff --git a/examples/statistical_charts/src/main.rs b/examples/statistical_charts/src/main.rs
index b8c83d34..f1c00633 100644
--- a/examples/statistical_charts/src/main.rs
+++ b/examples/statistical_charts/src/main.rs
@@ -4,7 +4,7 @@ use ndarray::Array;
use plotly::{
box_plot::{BoxMean, BoxPoints},
color::{NamedColor, Rgb, Rgba},
- common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation, Title},
+ common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation},
histogram::{Bins, Cumulative, HistFunc, HistNorm},
layout::{Axis, BarMode, BoxMode, Layout, Margin},
Bar, BoxPlot, Histogram, Plot, Scatter,
@@ -203,11 +203,7 @@ fn grouped_box_plot() {
plot.add_trace(trace3);
let layout = Layout::new()
- .y_axis(
- Axis::new()
- .title(Title::new("normalized moisture"))
- .zero_line(false),
- )
+ .y_axis(Axis::new().title("normalized moisture").zero_line(false))
.box_mode(BoxMode::Group);
plot.set_layout(layout);
@@ -248,7 +244,7 @@ fn box_plot_styling_outliers() {
.marker(Marker::new().color(Rgb::new(107, 174, 214)))
.box_points(BoxPoints::Outliers);
- let layout = Layout::new().title(Title::new("Box Plot Styling Outliers"));
+ let layout = Layout::new().title("Box Plot Styling Outliers");
let mut plot = Plot::new();
plot.set_layout(layout);
@@ -274,7 +270,7 @@ fn box_plot_styling_mean_and_standard_deviation() {
.name("Mean and Standard Deviation")
.marker(Marker::new().color(Rgb::new(8, 81, 156)))
.box_mean(BoxMean::StandardDeviation);
- let layout = Layout::new().title(Title::new("Box Plot Styling Mean and Standard Deviation"));
+ let layout = Layout::new().title("Box Plot Styling Mean and Standard Deviation");
let mut plot = Plot::new();
plot.set_layout(layout);
@@ -321,12 +317,8 @@ fn grouped_horizontal_box_plot() {
plot.add_trace(trace3);
let layout = Layout::new()
- .title(Title::new("Grouped Horizontal Box Plot"))
- .x_axis(
- Axis::new()
- .title(Title::new("normalized moisture"))
- .zero_line(false),
- )
+ .title("Grouped Horizontal Box Plot")
+ .x_axis(Axis::new().title("normalized moisture").zero_line(false))
.box_mode(BoxMode::Group);
plot.set_layout(layout);
@@ -370,9 +362,7 @@ fn fully_styled_box_plot() {
let mut plot = Plot::new();
let layout = Layout::new()
- .title(Title::new(
- "Points Scored by the Top 9 Scoring NBA Players in 2012",
- ))
+ .title("Points Scored by the Top 9 Scoring NBA Players in 2012")
.y_axis(
Axis::new()
.auto_range(true)
@@ -522,9 +512,9 @@ fn colored_and_styled_histograms() {
.auto_bin_x(false)
.x_bins(Bins::new(-3.2, 4.0, 0.06));
let layout = Layout::new()
- .title(Title::new("Colored and Styled Histograms"))
- .x_axis(Axis::new().title(Title::new("Value")))
- .y_axis(Axis::new().title(Title::new("Count")))
+ .title("Colored and Styled Histograms")
+ .x_axis(Axis::new().title("Value"))
+ .y_axis(Axis::new().title("Count"))
.bar_mode(BarMode::Overlay)
.bar_gap(0.05)
.bar_group_gap(0.2);
diff --git a/examples/subplots/src/main.rs b/examples/subplots/src/main.rs
index d96616a0..c78bde5a 100644
--- a/examples/subplots/src/main.rs
+++ b/examples/subplots/src/main.rs
@@ -194,7 +194,7 @@ fn multiple_custom_sized_subplots() {
plot.add_trace(trace4);
let layout = Layout::new()
- .title(Title::new("Multiple Custom Sized Subplots"))
+ .title("Multiple Custom Sized Subplots")
.x_axis(Axis::new().domain(&[0., 0.45]).anchor("y1"))
.y_axis(Axis::new().domain(&[0.5, 1.]).anchor("x1"))
.x_axis2(Axis::new().domain(&[0.55, 1.]).anchor("y2"))
@@ -220,11 +220,11 @@ fn two_y_axes() {
plot.add_trace(trace2);
let layout = Layout::new()
- .title(Title::new("Double Y Axis Example"))
- .y_axis(Axis::new().title(Title::new("yaxis title")))
+ .title("Double Y Axis Example")
+ .y_axis(Axis::new().title("yaxis title"))
.y_axis2(
Axis::new()
- .title(Title::new("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189))))
+ .title(Title::from("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189))))
.tick_font(Font::new().color(Rgb::new(148, 103, 189)))
.overlaying("y")
.side(AxisSide::Right),
@@ -249,17 +249,17 @@ fn multiple_axes() {
plot.add_trace(trace4);
let layout = Layout::new()
- .title(Title::new("multiple y-axes example"))
+ .title("multiple y-axes example")
.width(800)
.x_axis(Axis::new().domain(&[0.3, 0.7]))
.y_axis(
Axis::new()
- .title(Title::new("yaxis title").font(Font::new().color("#1f77b4")))
+ .title(Title::from("yaxis title").font(Font::new().color("#1f77b4")))
.tick_font(Font::new().color("#1f77b4")),
)
.y_axis2(
Axis::new()
- .title(Title::new("yaxis2 title").font(Font::new().color("#ff7f0e")))
+ .title(Title::from("yaxis2 title").font(Font::new().color("#ff7f0e")))
.tick_font(Font::new().color("#ff7f0e"))
.anchor("free")
.overlaying("y")
@@ -268,7 +268,7 @@ fn multiple_axes() {
)
.y_axis3(
Axis::new()
- .title(Title::new("yaxis3 title").font(Font::new().color("#d62728")))
+ .title(Title::from("yaxis3 title").font(Font::new().color("#d62728")))
.tick_font(Font::new().color("#d62728"))
.anchor("x")
.overlaying("y")
@@ -276,7 +276,7 @@ fn multiple_axes() {
)
.y_axis4(
Axis::new()
- .title(Title::new("yaxis4 title").font(Font::new().color("#9467bd")))
+ .title(Title::from("yaxis4 title").font(Font::new().color("#9467bd")))
.tick_font(Font::new().color("#9467bd"))
.anchor("free")
.overlaying("y")
diff --git a/examples/wasm-yew-minimal/src/main.rs b/examples/wasm-yew-minimal/src/main.rs
index f38ab848..cb0fb2bc 100644
--- a/examples/wasm-yew-minimal/src/main.rs
+++ b/examples/wasm-yew-minimal/src/main.rs
@@ -9,8 +9,7 @@ pub fn plot_component() -> Html {
let trace = Scatter::new(vec![0, 1, 2], vec![2, 1, 0]);
plot.add_trace(trace);
- let layout =
- plotly::Layout::new().title(plotly::common::Title::new("Displaying a Chart in Yew"));
+ let layout = plotly::Layout::new().title("Displaying a Chart in Yew");
plot.set_layout(layout);
async move {
diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs
index 4777afb5..74956fa2 100644
--- a/plotly/src/common/mod.rs
+++ b/plotly/src/common/mod.rs
@@ -58,14 +58,36 @@ pub enum HoverInfo {
#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, Default)]
pub struct LegendGroupTitle {
- text: String,
+ text: Option,
font: Option,
}
+impl From<&str> for LegendGroupTitle {
+ fn from(title: &str) -> Self {
+ LegendGroupTitle::with_text(title)
+ }
+}
+
+impl From for LegendGroupTitle {
+ fn from(value: String) -> Self {
+ LegendGroupTitle::with_text(value)
+ }
+}
+
+impl From<&String> for LegendGroupTitle {
+ fn from(value: &String) -> Self {
+ LegendGroupTitle::with_text(value)
+ }
+}
+
impl LegendGroupTitle {
- pub fn new(text: &str) -> Self {
- Self {
- text: text.to_string(),
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn with_text>(text: S) -> Self {
+ LegendGroupTitle {
+ text: Some(text.into()),
..Default::default()
}
}
@@ -976,8 +998,8 @@ impl ColorBar {
self
}
- pub fn title(mut self, title: Title) -> Self {
- self.title = Some(title);
+ pub fn title>(mut self, title: T) -> Self {
+ self.title = Some(title.into());
self
}
@@ -1235,7 +1257,7 @@ impl Pad {
#[serde_with::skip_serializing_none]
#[derive(Serialize, Clone, Debug, Default)]
pub struct Title {
- text: String,
+ text: Option,
font: Option,
side: Option,
#[serde(rename = "xref")]
@@ -1253,14 +1275,30 @@ pub struct Title {
impl From<&str> for Title {
fn from(title: &str) -> Self {
- Title::new(title)
+ Title::with_text(title)
+ }
+}
+
+impl From for Title {
+ fn from(value: String) -> Self {
+ Title::with_text(value)
+ }
+}
+
+impl From<&String> for Title {
+ fn from(value: &String) -> Self {
+ Title::with_text(value)
}
}
impl Title {
- pub fn new(text: &str) -> Self {
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn with_text>(text: S) -> Self {
Title {
- text: text.to_owned(),
+ text: Some(text.into()),
..Default::default()
}
}
@@ -1694,7 +1732,7 @@ mod tests {
.tick_width(55)
.tick0(0.0)
.ticks(Ticks::Outside)
- .title(Title::new("title"))
+ .title(Title::new())
.x(5.0)
.x_anchor(Anchor::Bottom)
.x_pad(2.2)
@@ -1735,7 +1773,7 @@ mod tests {
"tickwidth": 55,
"tick0": 0.0,
"ticks": "outside",
- "title": {"text": "title"},
+ "title": {},
"x": 5.0,
"xanchor": "bottom",
"xpad": 2.2,
@@ -2172,6 +2210,15 @@ mod tests {
assert_eq!(to_value(Reference::Paper).unwrap(), json!("paper"));
}
+ #[test]
+ #[rustfmt::skip]
+ fn test_serialize_legend_group_title() {
+ assert_eq!(to_value(LegendGroupTitle::new()).unwrap(), json!({}));
+ assert_eq!(to_value(LegendGroupTitle::with_text("title_str").font(Font::default())).unwrap(), json!({"font": {}, "text": "title_str"}));
+ assert_eq!(to_value(LegendGroupTitle::from(String::from("title_string"))).unwrap(), json!({"text" : "title_string"}));
+ assert_eq!(to_value(LegendGroupTitle::from(&String::from("title_string"))).unwrap(), json!({"text" : "title_string"}));
+ }
+
#[test]
fn test_serialize_pad() {
let pad = Pad::new(1, 2, 3);
@@ -2186,7 +2233,7 @@ mod tests {
#[test]
fn test_serialize_title() {
- let title = Title::new("title")
+ let title = Title::with_text("title")
.font(Font::new())
.side(Side::Top)
.x_ref(Reference::Paper)
@@ -2307,4 +2354,13 @@ mod tests {
assert_eq!(to_value(HoverOn::PointsAndFills).unwrap(), json!("points+fills"));
}
+
+ #[test]
+ #[allow(clippy::needless_borrows_for_generic_args)]
+ fn test_title_method_can_take_string() {
+ ColorBar::new().title("Title");
+ ColorBar::new().title(String::from("Title"));
+ ColorBar::new().title(&String::from("Title"));
+ ColorBar::new().title(Title::with_text("Title"));
+ }
}
diff --git a/plotly/src/layout/mod.rs b/plotly/src/layout/mod.rs
index d0d53f8d..7a70c23e 100644
--- a/plotly/src/layout/mod.rs
+++ b/plotly/src/layout/mod.rs
@@ -2180,7 +2180,7 @@ mod tests {
.y(2.0)
.y_anchor(Anchor::Left)
.valign(VAlign::Middle)
- .title(Title::new("title"))
+ .title("title")
.group_click(GroupClick::ToggleItem)
.item_width(50);
@@ -2430,7 +2430,7 @@ mod tests {
let axis = Axis::new()
.visible(false)
.color("#678123")
- .title(Title::new("title"))
+ .title(Title::with_text("title"))
.type_(AxisType::Date)
.auto_range(false)
.range_mode(RangeMode::NonNegative)
@@ -2962,7 +2962,7 @@ mod tests {
#[test]
fn test_serialize_layout_template() {
let layout_template = LayoutTemplate::new()
- .title("Title".into())
+ .title("Title")
.show_legend(false)
.legend(Legend::new())
.margin(Margin::new())
@@ -3104,7 +3104,9 @@ mod tests {
#[test]
fn test_serialize_layout() {
let layout = Layout::new()
- .title("Title".into())
+ .title("Title")
+ .title(String::from("Title"))
+ .title(Title::with_text("Title"))
.show_legend(false)
.legend(Legend::new())
.margin(Margin::new())
diff --git a/plotly/src/layout/themes.rs b/plotly/src/layout/themes.rs
index a4fb2774..a687caa7 100644
--- a/plotly/src/layout/themes.rs
+++ b/plotly/src/layout/themes.rs
@@ -62,7 +62,7 @@ pub static PLOTLY_WHITE: Lazy = Lazy::new(|| {
.hover_mode(HoverMode::Closest)
.paper_background_color("#ffffff")
.plot_background_color("#ffffff")
- .title(Title::new("").x(0.05))
+ .title(Title::new().x(0.05))
.x_axis(
Axis::new()
.auto_margin(true)
@@ -138,7 +138,7 @@ pub static PLOTLY_DARK: Lazy = Lazy::new(|| {
.hover_mode(HoverMode::Closest)
.paper_background_color("#111111")
.plot_background_color("#111111")
- .title(Title::new("").x(0.05))
+ .title(Title::new().x(0.05))
.x_axis(
Axis::new()
.auto_margin(true)
@@ -165,6 +165,31 @@ mod tests {
use super::*;
use crate::*;
+ #[test]
+ fn test_plotly_default() {
+ let template = &*DEFAULT;
+ let layout = Layout::new().template(template);
+ let mut plot = Plot::new();
+ plot.set_layout(layout);
+ plot.add_trace(Bar::new(vec![0], vec![1]));
+
+ let expected = r##"{"template":{"layout":{}}}"##; // etc...
+ assert!(plot.to_json().contains(expected));
+ }
+
+ #[test]
+ fn test_plotly_white() {
+ let template = &*PLOTLY_WHITE;
+ let layout = Layout::new().template(template);
+ let mut plot = Plot::new();
+ plot.set_layout(layout);
+ plot.add_trace(Bar::new(vec![0], vec![1]));
+ dbg!(plot.to_json());
+
+ let expected = r##"{"template":{"layout":{"title":{"x":0.05},"font":{"color":"#2a3f5f"}"##; // etc...
+ assert!(plot.to_json().contains(expected));
+ }
+
#[test]
fn test_plotly_dark() {
let template = &*PLOTLY_DARK;
@@ -173,8 +198,7 @@ mod tests {
plot.set_layout(layout);
plot.add_trace(Bar::new(vec![0], vec![1]));
- let expected =
- r##"{"template":{"layout":{"title":{"text":"","x":0.05},"font":{"color":"#f2f5fa"}"##; // etc...
+ let expected = r##"{"template":{"layout":{"title":{"x":0.05},"font":{"color":"#f2f5fa"}"##; // etc...
assert!(plot.to_json().contains(expected));
}
}
diff --git a/plotly/src/layout/update_menu.rs b/plotly/src/layout/update_menu.rs
index eea463f0..f662a7f2 100644
--- a/plotly/src/layout/update_menu.rs
+++ b/plotly/src/layout/update_menu.rs
@@ -246,10 +246,7 @@ mod tests {
use serde_json::{json, to_value};
use super::*;
- use crate::{
- common::{Title, Visible},
- Layout,
- };
+ use crate::{common::Visible, Layout};
#[test]
fn test_serialize_button_method() {
@@ -315,7 +312,7 @@ mod tests {
Visible::True,
Visible::False,
]))
- .push_relayout(Layout::modify_title(Title::new("Hello")))
+ .push_relayout(Layout::modify_title("Hello"))
.push_relayout(Layout::modify_width(20))
.build();
diff --git a/plotly/src/plot.rs b/plotly/src/plot.rs
index 03fe4ae0..d02fe92d 100644
--- a/plotly/src/plot.rs
+++ b/plotly/src/plot.rs
@@ -161,7 +161,7 @@ impl Traces {
/// plot.add_trace(trace2);
/// plot.add_trace(trace3);
///
-/// let layout = Layout::new().title("Line and Scatter Plot".into());
+/// let layout = Layout::new().title("Line and Scatter Plot");
/// plot.set_layout(layout);
///
/// # if false { // We don't actually want to try and display the plot in a browser when running a doctest.
@@ -463,7 +463,7 @@ impl Plot {
fn show_with_default_app(temp_path: &str) {
use std::process::Command;
Command::new("open")
- .args(&[temp_path])
+ .args([temp_path])
.output()
.expect(DEFAULT_HTML_APP_NOT_FOUND);
}
@@ -548,7 +548,7 @@ mod tests {
#[test]
fn test_plot_serialize_with_layout() {
let mut plot = create_test_plot();
- let layout = Layout::new().title("Title".into());
+ let layout = Layout::new().title("Title");
plot.set_layout(layout);
let expected = json!({
@@ -597,7 +597,7 @@ mod tests {
#[test]
fn test_layout_to_json() {
let mut plot = create_test_plot();
- let layout = Layout::new().title("TestTitle".into());
+ let layout = Layout::new().title("TestTitle");
plot.set_layout(layout);
let expected = json!({
@@ -651,7 +651,7 @@ mod tests {
assert!(!dst.exists());
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(target_os = "linux")]
#[test]
#[cfg(feature = "kaleido")]
fn test_save_to_png() {
@@ -663,7 +663,7 @@ mod tests {
assert!(!dst.exists());
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(target_os = "linux")]
#[test]
#[cfg(feature = "kaleido")]
fn test_save_to_jpeg() {
@@ -675,7 +675,7 @@ mod tests {
assert!(!dst.exists());
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(target_os = "linux")]
#[test]
#[cfg(feature = "kaleido")]
fn test_save_to_svg() {
@@ -699,7 +699,7 @@ mod tests {
assert!(!dst.exists());
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(target_os = "linux")]
#[test]
#[cfg(feature = "kaleido")]
fn test_save_to_pdf() {
@@ -711,7 +711,7 @@ mod tests {
assert!(!dst.exists());
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(target_os = "linux")]
#[test]
#[cfg(feature = "kaleido")]
fn test_save_to_webp() {
diff --git a/plotly/src/traces/bar.rs b/plotly/src/traces/bar.rs
index 16300ae6..0acaed0d 100644
--- a/plotly/src/traces/bar.rs
+++ b/plotly/src/traces/bar.rs
@@ -159,7 +159,7 @@ mod tests {
.inside_text_anchor(TextAnchor::End)
.inside_text_font(Font::new())
.legend_group("legend-group")
- .legend_group_title(LegendGroupTitle::new("legend-group-title"))
+ .legend_group_title("legend-group-title")
.marker(Marker::new())
.name("Bar")
.offset(5)
diff --git a/plotly/src/traces/box_plot.rs b/plotly/src/traces/box_plot.rs
index 5b8e9c91..8903c480 100644
--- a/plotly/src/traces/box_plot.rs
+++ b/plotly/src/traces/box_plot.rs
@@ -283,7 +283,7 @@ mod tests {
.jitter(0.5)
.line(Line::new())
.legend_group("one")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.lower_fence(vec![0., 1.])
.marker(Marker::new())
.mean(vec![12., 13.])
diff --git a/plotly/src/traces/candlestick.rs b/plotly/src/traces/candlestick.rs
index 2fe6a197..64b25a5b 100644
--- a/plotly/src/traces/candlestick.rs
+++ b/plotly/src/traces/candlestick.rs
@@ -144,7 +144,7 @@ mod tests {
.visible(Visible::True)
.show_legend(false)
.legend_group("group_1")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.opacity(0.3)
.text_array(vec!["text", "here"])
.text("text here")
diff --git a/plotly/src/traces/contour.rs b/plotly/src/traces/contour.rs
index 844f55c2..576e58f1 100644
--- a/plotly/src/traces/contour.rs
+++ b/plotly/src/traces/contour.rs
@@ -339,8 +339,11 @@ where
Box::new(self)
}
- pub fn legend_group_title(mut self, legend_group_title: LegendGroupTitle) -> Box {
- self.legend_group_title = Some(legend_group_title);
+ pub fn legend_group_title(
+ mut self,
+ legend_group_title: impl Into,
+ ) -> Box {
+ self.legend_group_title = Some(legend_group_title.into());
Box::new(self)
}
@@ -583,7 +586,7 @@ mod tests {
.hover_template_array(vec!["ok {1}", "ok {2}"])
.hover_text(vec!["p3", "p4"])
.legend_group("group_1")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.line(Line::new())
.n_contours(5)
.name("contour trace")
diff --git a/plotly/src/traces/heat_map.rs b/plotly/src/traces/heat_map.rs
index 07c216ed..811dcfb6 100644
--- a/plotly/src/traces/heat_map.rs
+++ b/plotly/src/traces/heat_map.rs
@@ -206,7 +206,7 @@ mod tests {
.hover_template_array(vec!["tmpl1", "tmpl2"])
.hover_text(vec!["hov", "er"])
.legend_group("1")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.name("name")
.opacity(0.99)
.reverse_scale(false)
diff --git a/plotly/src/traces/histogram.rs b/plotly/src/traces/histogram.rs
index 7ae6dd59..b4b9b97f 100644
--- a/plotly/src/traces/histogram.rs
+++ b/plotly/src/traces/histogram.rs
@@ -410,7 +410,7 @@ mod tests {
.hover_text("hover_text")
.hover_text_array(vec!["hover_text_1", "hover_text_2"])
.legend_group("legendgroup")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.marker(Marker::new())
.n_bins_x(5)
.n_bins_y(10)
diff --git a/plotly/src/traces/image.rs b/plotly/src/traces/image.rs
index 4efbf0c9..d081f9b4 100644
--- a/plotly/src/traces/image.rs
+++ b/plotly/src/traces/image.rs
@@ -408,7 +408,7 @@ mod tests {
.name("image name")
.visible(Visible::True)
.legend_rank(1000)
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.opacity(0.5)
.ids(vec!["one"])
.x0(0.0)
diff --git a/plotly/src/traces/mesh3d.rs b/plotly/src/traces/mesh3d.rs
index fae98c9a..fc45d781 100644
--- a/plotly/src/traces/mesh3d.rs
+++ b/plotly/src/traces/mesh3d.rs
@@ -493,7 +493,7 @@ mod tests {
.show_legend(true)
.legend_rank(1000)
.legend_group("legend_group")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.opacity(0.5)
.ids(vec!["one"])
.face_color(vec!["#ff00ff"])
diff --git a/plotly/src/traces/ohlc.rs b/plotly/src/traces/ohlc.rs
index cf1b4e50..7067514f 100644
--- a/plotly/src/traces/ohlc.rs
+++ b/plotly/src/traces/ohlc.rs
@@ -28,7 +28,7 @@ use crate::{
/// let expected = serde_json::json!({
/// "type": "ohlc",
/// "x": ["2022-08-22", "2022-08-23"],
-/// "open": [5, 6],
+/// "open": [5, 6],
/// "high": [8, 10],
/// "low": [2, 4],
/// "close": [6, 7]
@@ -133,7 +133,7 @@ mod test {
.hover_text("1")
.increasing(Direction::Increasing { line: Line::new() })
.legend_group("legendgroup")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.line(Line::new())
.name("ohlc_trace")
.opacity(0.4)
diff --git a/plotly/src/traces/sankey.rs b/plotly/src/traces/sankey.rs
index 1a53d2c8..be96afa2 100644
--- a/plotly/src/traces/sankey.rs
+++ b/plotly/src/traces/sankey.rs
@@ -436,7 +436,7 @@ mod tests {
.name("sankey")
.visible(true)
.legend_rank(1000)
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.ids(vec!["one"])
.hover_info(HoverInfo::All)
.hover_label(Label::new())
diff --git a/plotly/src/traces/scatter.rs b/plotly/src/traces/scatter.rs
index caa2a076..fe9f5b9c 100644
--- a/plotly/src/traces/scatter.rs
+++ b/plotly/src/traces/scatter.rs
@@ -456,7 +456,7 @@ mod tests {
.hover_template_array(vec!["hover_template"])
.ids(vec!["1"])
.legend_group("legend_group")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.line(Line::new())
.marker(Marker::new())
.meta("meta")
diff --git a/plotly/src/traces/scatter3d.rs b/plotly/src/traces/scatter3d.rs
index 66c72c03..412ba1f8 100644
--- a/plotly/src/traces/scatter3d.rs
+++ b/plotly/src/traces/scatter3d.rs
@@ -367,7 +367,7 @@ mod tests {
.ids(vec!["1"])
.legend_group("legend_group")
.legend_rank(1000)
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.line(Line::new())
.marker(Marker::new())
.meta("meta")
diff --git a/plotly/src/traces/scatter_mapbox.rs b/plotly/src/traces/scatter_mapbox.rs
index 1ee3c164..76348e6a 100644
--- a/plotly/src/traces/scatter_mapbox.rs
+++ b/plotly/src/traces/scatter_mapbox.rs
@@ -311,7 +311,7 @@ mod tests {
.show_legend(true)
.legend_rank(1000)
.legend_group("legend group")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.opacity(0.5)
.mode(Mode::LinesText)
.ids(vec!["one"])
diff --git a/plotly/src/traces/scatter_polar.rs b/plotly/src/traces/scatter_polar.rs
index ae3ed244..a9101607 100644
--- a/plotly/src/traces/scatter_polar.rs
+++ b/plotly/src/traces/scatter_polar.rs
@@ -368,7 +368,7 @@ mod tests {
.hover_text_array(vec!["hover_text"])
.ids(vec!["1"])
.legend_group("legend_group")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.line(Line::new())
.marker(Marker::new())
.meta("meta")
diff --git a/plotly/src/traces/surface.rs b/plotly/src/traces/surface.rs
index b4110d3b..3f692543 100644
--- a/plotly/src/traces/surface.rs
+++ b/plotly/src/traces/surface.rs
@@ -328,7 +328,7 @@ mod tests {
.hover_text("hover_text")
.hover_text_array(vec!["hover_text_1"])
.legend_group("legend_group")
- .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
+ .legend_group_title("Legend Group Title")
.lighting(Lighting::new())
.light_position(Position::new(0, 0, 0))
.name("surface_trace")
diff --git a/plotly_derive/src/field_setter.rs b/plotly_derive/src/field_setter.rs
index f330be21..ca13d1d3 100644
--- a/plotly_derive/src/field_setter.rs
+++ b/plotly_derive/src/field_setter.rs
@@ -140,6 +140,8 @@ enum FieldType {
OptionString,
OptionNumOrString,
OptionNumOrStringCollection,
+ OptionTitle,
+ OptionLegendGroupTitle,
OptionOther(syn::Type),
}
@@ -202,6 +204,8 @@ impl FieldType {
FieldType::OptionNumOrStringCollection => quote![crate::private::NumOrStringCollection],
FieldType::OptionOther(inner) => quote![#inner],
FieldType::OptionBoxOther(inner) => quote![Box<#inner>],
+ FieldType::OptionTitle => quote![Title],
+ FieldType::OptionLegendGroupTitle => quote![LegendGroupTitle],
}
}
@@ -225,6 +229,8 @@ impl FieldType {
["Box", "Color"] => FieldType::OptionBoxColor,
["Box", ..] => FieldType::OptionBoxOther(types.get(2).cloned().unwrap()),
["Vec", "Box", "Color"] => FieldType::OptionVecBoxColor,
+ ["Title"] => FieldType::OptionTitle,
+ ["LegendGroupTitle"] => FieldType::OptionLegendGroupTitle,
_ => FieldType::OptionOther(types.get(1).cloned().unwrap()),
}
}
@@ -344,6 +350,12 @@ impl FieldReceiver {
quote![value.into()],
quote![],
),
+ FieldType::OptionTitle => (quote![impl Into], quote![value.into()], quote![]),
+ FieldType::OptionLegendGroupTitle => (
+ quote![impl Into],
+ quote![value.into()],
+ quote![],
+ ),
};
struct ModifyEnum {
diff --git a/plotly_kaleido/src/lib.rs b/plotly_kaleido/src/lib.rs
index 199c77fe..f6641c25 100644
--- a/plotly_kaleido/src/lib.rs
+++ b/plotly_kaleido/src/lib.rs
@@ -239,7 +239,8 @@ mod tests {
assert_eq!(to_value(kaleido_data).unwrap(), expected);
}
- #[cfg(not(target_os = "windows"))]
+ // This seems to fail unpredictably on MacOs.
+ #[cfg(target_os = "linux")]
#[test]
fn test_save_png() {
let test_plot = create_test_plot();
@@ -250,7 +251,8 @@ mod tests {
assert!(std::fs::remove_file(dst.as_path()).is_ok());
}
- #[cfg(not(target_os = "windows"))]
+ // This seems to fail unpredictably on MacOs.
+ #[cfg(target_os = "linux")]
#[test]
fn test_save_jpeg() {
let test_plot = create_test_plot();
@@ -261,7 +263,8 @@ mod tests {
assert!(std::fs::remove_file(dst.as_path()).is_ok());
}
- #[cfg(not(target_os = "windows"))]
+ // This seems to fail unpredictably on MacOs.
+ #[cfg(target_os = "linux")]
#[test]
fn test_save_webp() {
let test_plot = create_test_plot();
@@ -272,7 +275,8 @@ mod tests {
assert!(std::fs::remove_file(dst.as_path()).is_ok());
}
- #[cfg(not(target_os = "windows"))]
+ // This seems to fail unpredictably on MacOs.
+ #[cfg(target_os = "linux")]
#[test]
fn test_save_svg() {
let test_plot = create_test_plot();
@@ -283,7 +287,8 @@ mod tests {
assert!(std::fs::remove_file(dst.as_path()).is_ok());
}
- #[cfg(not(target_os = "windows"))]
+ // This seems to fail unpredictably on MacOs.
+ #[cfg(target_os = "linux")]
#[test]
fn test_save_pdf() {
let test_plot = create_test_plot();
@@ -294,6 +299,7 @@ mod tests {
assert!(std::fs::remove_file(dst.as_path()).is_ok());
}
+ // This doesn't work for some reason
#[test]
#[ignore]
fn test_save_eps() {