plotly_fork/traces/
bar.rs

1//! Bar trace
2
3use plotly_derive::FieldSetter;
4use serde::Serialize;
5
6use crate::{
7    common::{
8        Calendar, ConstrainText, Dim, ErrorData, Font, HoverInfo, Label, LegendGroupTitle, Marker,
9        Orientation, PlotType, TextAnchor, TextPosition, Visible,
10    },
11    Trace,
12};
13
14/// Construct a bar trace.
15///
16/// # Examples
17///
18/// ```
19/// use plotly::Bar;
20///
21/// let x = vec![0, 1, 2, 3, 4, 5];
22/// let y = vec![0, 2, 4, 6, 8, 10];
23///
24/// let trace = Bar::new(x, y).show_legend(true).opacity(0.5);
25///
26/// let expected = serde_json::json!({
27///     "type": "bar",
28///     "x": [0, 1, 2, 3, 4, 5],
29///     "y": [0, 2, 4, 6, 8, 10],
30///     "showlegend": true,
31///     "opacity": 0.5
32/// });
33///
34/// assert_eq!(serde_json::to_value(trace).unwrap(), expected);
35/// ```
36#[serde_with::skip_serializing_none]
37#[derive(Serialize, Debug, Clone, FieldSetter)]
38#[field_setter(box_self, kind = "trace")]
39pub struct Bar<X, Y>
40where
41    X: Serialize + Clone,
42    Y: Serialize + Clone,
43{
44    #[field_setter(default = "PlotType::Bar")]
45    r#type: PlotType,
46    x: Option<Vec<X>>,
47    y: Option<Vec<Y>>,
48    name: Option<String>,
49    visible: Option<Visible>,
50    #[serde(rename = "showlegend")]
51    show_legend: Option<bool>,
52    #[serde(rename = "legendgroup")]
53    legend_group: Option<String>,
54    #[serde(rename = "legendgrouptitle")]
55    legend_group_title: Option<LegendGroupTitle>,
56    opacity: Option<f64>,
57    ids: Option<Vec<String>>,
58    width: Option<usize>,
59    offset: Option<Dim<usize>>,
60    text: Option<Dim<String>>,
61    #[serde(rename = "textposition")]
62    text_position: Option<Dim<TextPosition>>,
63    #[serde(rename = "texttemplate")]
64    text_template: Option<Dim<String>>,
65    #[serde(rename = "hovertext")]
66    hover_text: Option<Dim<String>>,
67    #[serde(rename = "hoverinfo")]
68    hover_info: Option<HoverInfo>,
69    #[serde(rename = "hovertemplate")]
70    hover_template: Option<Dim<String>>,
71    #[serde(rename = "xaxis")]
72    x_axis: Option<String>,
73    #[serde(rename = "yaxis")]
74    y_axis: Option<String>,
75    orientation: Option<Orientation>,
76    #[serde(rename = "alignmentgroup")]
77    alignment_group: Option<String>,
78    #[serde(rename = "offsetgroup")]
79    offset_group: Option<String>,
80    marker: Option<Marker>,
81    #[serde(rename = "textangle")]
82    text_angle: Option<f64>,
83    #[serde(rename = "textfont")]
84    text_font: Option<Font>,
85    error_x: Option<ErrorData>,
86    error_y: Option<ErrorData>,
87    #[serde(rename = "cliponaxis")]
88    clip_on_axis: Option<bool>,
89    #[serde(rename = "constraintext")]
90    constrain_text: Option<ConstrainText>,
91    #[serde(rename = "hoverlabel")]
92    hover_label: Option<Label>,
93    #[serde(rename = "insidetextanchor")]
94    inside_text_anchor: Option<TextAnchor>,
95    #[serde(rename = "insidetextfont")]
96    inside_text_font: Option<Font>,
97    #[serde(rename = "outsidetextfont")]
98    outside_text_font: Option<Font>,
99    #[serde(rename = "xcalendar")]
100    x_calendar: Option<Calendar>,
101    #[serde(rename = "ycalendar")]
102    y_calendar: Option<Calendar>,
103}
104
105impl<X, Y> Bar<X, Y>
106where
107    X: Serialize + Clone,
108    Y: Serialize + Clone,
109{
110    pub fn new(x: Vec<X>, y: Vec<Y>) -> Box<Self> {
111        Box::new(Bar {
112            x: Some(x),
113            y: Some(y),
114            ..Default::default()
115        })
116    }
117}
118
119impl<X, Y> Trace for Bar<X, Y>
120where
121    X: Serialize + Clone,
122    Y: Serialize + Clone,
123{
124    fn to_json(&self) -> String {
125        serde_json::to_string(self).unwrap()
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use serde_json::{json, to_value};
132
133    use super::*;
134    use crate::common::ErrorType;
135
136    #[test]
137    fn test_default_bar() {
138        let trace: Bar<i32, i32> = Bar::default();
139        let expected = json!({"type": "bar"}).to_string();
140
141        assert_eq!(trace.to_json(), expected);
142    }
143
144    #[test]
145    fn test_serialize_bar() {
146        let bar = Bar::new(vec![1, 2], vec![3, 4])
147            .alignment_group("alignment_group")
148            .clip_on_axis(true)
149            .constrain_text(ConstrainText::Both)
150            .error_x(ErrorData::new(ErrorType::Constant))
151            .error_y(ErrorData::new(ErrorType::Percent))
152            .hover_info(HoverInfo::All)
153            .hover_label(Label::new())
154            .hover_template("tmpl")
155            .hover_template_array(vec!["tmpl1", "tmpl2"])
156            .hover_text("hover_text")
157            .hover_text_array(vec!["hover_text"])
158            .ids(vec!["1"])
159            .inside_text_anchor(TextAnchor::End)
160            .inside_text_font(Font::new())
161            .legend_group("legend-group")
162            .legend_group_title(LegendGroupTitle::new("legend-group-title"))
163            .marker(Marker::new())
164            .name("Bar")
165            .offset(5)
166            .offset_array(vec![5, 5])
167            .offset_group("offset_group")
168            .opacity(0.5)
169            .orientation(Orientation::Vertical)
170            .outside_text_font(Font::new())
171            .show_legend(false)
172            .text("text")
173            .text_angle(0.05)
174            .text_array(vec!["text"])
175            .text_font(Font::new())
176            .text_position(TextPosition::None)
177            .text_position_array(vec![TextPosition::None])
178            .text_template("text_template")
179            .text_template_array(vec!["text_template"])
180            .visible(Visible::LegendOnly)
181            .width(999)
182            .x_axis("xaxis")
183            .x_calendar(Calendar::Nanakshahi)
184            .y_axis("yaxis")
185            .y_calendar(Calendar::Ummalqura);
186
187        let expected = json!({
188            "type": "bar",
189            "hoverinfo": "all",
190            "hovertemplate": ["tmpl1", "tmpl2"],
191            "x": [1, 2],
192            "y": [3, 4],
193            "name": "Bar",
194            "visible": "legendonly",
195            "showlegend": false,
196            "legendgroup": "legend-group",
197            "legendgrouptitle": {"text": "legend-group-title"},
198            "opacity": 0.5,
199            "ids": ["1"],
200            "width": 999,
201            "offset": [5, 5],
202            "text": ["text"],
203            "textposition": ["none"],
204            "texttemplate": ["text_template"],
205            "hovertext": ["hover_text"],
206            "xaxis": "xaxis",
207            "yaxis": "yaxis",
208            "orientation": "v",
209            "alignmentgroup": "alignment_group",
210            "offsetgroup": "offset_group",
211            "marker": {},
212            "textangle": 0.05,
213            "textfont": {},
214            "error_x": {"type": "constant"},
215            "error_y": {"type": "percent"},
216            "cliponaxis": true,
217            "constraintext": "both",
218            "hoverlabel": {},
219            "insidetextanchor": "end",
220            "insidetextfont": {},
221            "outsidetextfont": {},
222            "xcalendar": "nanakshahi",
223            "ycalendar": "ummalqura",
224        });
225
226        assert_eq!(to_value(bar).unwrap(), expected);
227    }
228}