From c4694c1624c5091e48e48f4c4869400f018ec99d Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Tue, 3 Jun 2025 23:02:45 +0200 Subject: [PATCH 1/8] split layout into multiple modules Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- plotly/src/layout/annotation.rs | 420 ++++++++++++++++++++++++++++++++ plotly/src/layout/mod.rs | 395 +----------------------------- 2 files changed, 424 insertions(+), 391 deletions(-) create mode 100644 plotly/src/layout/annotation.rs diff --git a/plotly/src/layout/annotation.rs b/plotly/src/layout/annotation.rs new file mode 100644 index 00000000..6ef0bb5d --- /dev/null +++ b/plotly/src/layout/annotation.rs @@ -0,0 +1,420 @@ +use plotly_derive::FieldSetter; +use serde::{Serialize, Serializer}; + +use crate::color::Color; +use crate::common::{Anchor, Font, Label}; +use crate::private::NumOrString; + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "lowercase")] +pub enum VAlign { + Top, + Middle, + Bottom, +} + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "lowercase")] +pub enum HAlign { + Left, + Center, + Right, +} + +#[derive(Serialize, Debug, Clone)] +#[serde(rename_all = "lowercase")] +pub enum ArrowSide { + End, + Start, + #[serde(rename = "end+start")] + StartEnd, + None, +} + +#[derive(Debug, Clone)] +pub enum ClickToShow { + False, + OnOff, + OnOut, +} + +impl Serialize for ClickToShow { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + Self::False => serializer.serialize_bool(false), + Self::OnOff => serializer.serialize_str("onoff"), + Self::OnOut => serializer.serialize_str("onout"), + } + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Debug, Clone, FieldSetter)] +pub struct Annotation { + /// Determines whether or not this annotation is visible. + visible: Option, + /// Sets the text associated with this annotation. Plotly uses a subset of + /// HTML tags to do things like newline (
), bold (), italics + /// (), hyperlinks (). Tags , , + /// are also supported. + text: Option, + /// Sets the angle at which the `text` is drawn with respect to the + /// horizontal. + #[serde(rename = "textangle")] + text_angle: Option, + /// Sets the annotation text font. + font: Option, + /// Sets an explicit width for the text box. null (default) lets the text + /// set the box width. Wider text will be clipped. There is no automatic + /// wrapping; use
to start a new line. + width: Option, + /// Sets an explicit height for the text box. null (default) lets the text + /// set the box height. Taller text will be clipped. + height: Option, + /// Sets the opacity of the annotation (text + arrow). + opacity: Option, + /// Sets the horizontal alignment of the `text` within the box. Has an + /// effect only if `text` spans two or more lines (i.e. `text` contains + /// one or more
HTML tags) or if an explicit width is set to + /// override the text width. + align: Option, + /// Sets the vertical alignment of the `text` within the box. Has an effect + /// only if an explicit height is set to override the text height. + valign: Option, + /// Sets the background color of the annotation. + #[serde(rename = "bgcolor")] + background_color: Option>, + /// Sets the color of the border enclosing the annotation `text`. + #[serde(rename = "bordercolor")] + border_color: Option>, + /// Sets the padding (in px) between the `text` and the enclosing border. + #[serde(rename = "borderpad")] + border_pad: Option, + /// Sets the width (in px) of the border enclosing the annotation `text`. + #[serde(rename = "borderwidth")] + border_width: Option, + /// Determines whether or not the annotation is drawn with an arrow. If + /// "True", `text` is placed near the arrow's tail. If "False", `text` + /// lines up with the `x` and `y` provided. + #[serde(rename = "showarrow")] + show_arrow: Option, + /// Sets the color of the annotation arrow. + #[serde(rename = "arrowcolor")] + arrow_color: Option>, + /// Sets the end annotation arrow head style. Integer between or equal to 0 + /// and 8. + #[serde(rename = "arrowhead")] + arrow_head: Option, + /// Sets the start annotation arrow head style. Integer between or equal to + /// 0 and 8. + #[serde(rename = "startarrowhead")] + start_arrow_head: Option, + /// Sets the annotation arrow head position. + #[serde(rename = "arrowside")] + arrow_side: Option, + /// Sets the size of the end annotation arrow head, relative to + /// `arrowwidth`. A value of 1 (default) gives a head about 3x as wide + /// as the line. + #[serde(rename = "arrowsize")] + arrow_size: Option, + /// Sets the size of the start annotation arrow head, relative to + /// `arrowwidth`. A value of 1 (default) gives a head about 3x as wide + /// as the line. + #[serde(rename = "startarrowsize")] + start_arrow_size: Option, + /// Sets the width (in px) of annotation arrow line. + #[serde(rename = "arrowwidth")] + arrow_width: Option, + /// Sets a distance, in pixels, to move the end arrowhead away from the + /// position it is pointing at, for example to point at the edge of a + /// marker independent of zoom. Note that this shortens the arrow from + /// the `ax` / `ay` vector, in contrast to `xshift` / `yshift` which + /// moves everything by this amount. + #[serde(rename = "standoff")] + stand_off: Option, + /// Sets a distance, in pixels, to move the start arrowhead away from the + /// position it is pointing at, for example to point at the edge of a + /// marker independent of zoom. Note that this shortens the arrow from + /// the `ax` / `ay` vector, in contrast to `xshift` / `yshift` + /// which moves everything by this amount. + #[serde(rename = "startstandoff")] + start_stand_off: Option, + /// Sets the x component of the arrow tail about the arrow head. If `axref` + /// is `pixel`, a positive (negative) component corresponds to an arrow + /// pointing from right to left (left to right). If `axref` is an axis, + /// this is an absolute value on that axis, like `x`, NOT a + /// relative value. + ax: Option, + /// Sets the y component of the arrow tail about the arrow head. If `ayref` + /// is `pixel`, a positive (negative) component corresponds to an arrow + /// pointing from bottom to top (top to bottom). If `ayref` is an axis, + /// this is an absolute value on that axis, like `y`, NOT a + /// relative value. + ay: Option, + /// Indicates in what terms the tail of the annotation (ax,ay) is specified. + /// If `pixel`, `ax` is a relative offset in pixels from `x`. If set to + /// an x axis id (e.g. "x" or "x2"), `ax` is specified in the same terms + /// as that axis. This is useful for trendline annotations which + /// should continue to indicate the correct trend when zoomed. + #[serde(rename = "axref")] + ax_ref: Option, + /// Indicates in what terms the tail of the annotation (ax,ay) is specified. + /// If `pixel`, `ay` is a relative offset in pixels from `y`. If set to + /// a y axis id (e.g. "y" or "y2"), `ay` is specified in the same terms + /// as that axis. This is useful for trendline annotations which + /// should continue to indicate the correct trend when zoomed. + #[serde(rename = "ayref")] + ay_ref: Option, + /// Sets the annotation's x coordinate axis. If set to an x axis id (e.g. + /// "x" or "x2"), the `x` position refers to an x coordinate If set to + /// "paper", the `x` position refers to the distance from the left side + /// of the plotting area in normalized coordinates where 0 (1) + /// corresponds to the left (right) side. + #[serde(rename = "xref")] + x_ref: Option, + /// Sets the annotation's x position. If the axis `type` is "log", then you + /// must take the log of your desired range. If the axis `type` is + /// "date", it should be date strings, like date data, though Date + /// objects and unix milliseconds will be accepted and converted to strings. + /// If the axis `type` is "category", it should be numbers, using the scale + /// where each category is assigned a serial number from zero in the + /// order it appears. + x: Option, + /// Sets the text box's horizontal position anchor This anchor binds the `x` + /// position to the "left", "center" or "right" of the annotation. For + /// example, if `x` is set to 1, `xref` to "paper" and `xanchor` to + /// "right" then the right-most portion of the annotation lines up with + /// the right-most edge of the plotting area. If "auto", the anchor is + /// equivalent to "center" for data-referenced annotations or if there + /// is an arrow, whereas for paper-referenced with no arrow, the anchor + /// picked corresponds to the closest side. + #[serde(rename = "xanchor")] + x_anchor: Option, + /// Shifts the position of the whole annotation and arrow to the right + /// (positive) or left (negative) by this many pixels. + #[serde(rename = "xshift")] + x_shift: Option, + /// Sets the annotation's y coordinate axis. If set to an y axis id (e.g. + /// "y" or "y2"), the `y` position refers to an y coordinate If set to + /// "paper", the `y` position refers to the distance from the bottom of + /// the plotting area in normalized coordinates where 0 (1) corresponds + /// to the bottom (top). + #[serde(rename = "yref")] + y_ref: Option, + /// Sets the annotation's y position. If the axis `type` is "log", then you + /// must take the log of your desired range. If the axis `type` is + /// "date", it should be date strings, like date data, though Date + /// objects and unix milliseconds will be accepted and converted to strings. + /// If the axis `type` is "category", it should be numbers, using the + /// scale where each category is assigned a serial number from zero in + /// the order it appears. + y: Option, + /// Sets the text box's vertical position anchor This anchor binds the `y` + /// position to the "top", "middle" or "bottom" of the annotation. For + /// example, if `y` is set to 1, `yref` to "paper" and `yanchor` to + /// "top" then the top-most portion of the annotation lines up with the + /// top-most edge of the plotting area. If "auto", the anchor is equivalent + /// to "middle" for data-referenced annotations or if there is an arrow, + /// whereas for paper-referenced with no arrow, the anchor picked + /// corresponds to the closest side. + #[serde(rename = "yanchor")] + y_anchor: Option, + /// Shifts the position of the whole annotation and arrow up (positive) or + /// down (negative) by this many pixels. + #[serde(rename = "yshift")] + y_shift: Option, + /// Makes this annotation respond to clicks on the plot. If you click a data + /// point that exactly matches the `x` and `y` values of this + /// annotation, and it is hidden (visible: false), it will appear. In + /// "onoff" mode, you must click the same point again to make it disappear, + /// so if you click multiple points, you can show multiple annotations. + /// In "onout" mode, a click anywhere else in the plot (on another data + /// point or not) will hide this annotation. If you need to show/hide + /// this annotation in response to different `x` or `y` values, you can set + /// `xclick` and/or `yclick`. This is useful for example to label the side + /// of a bar. To label markers though, `standoff` is preferred over + /// `xclick` and `yclick`. + #[serde(rename = "clicktoshow")] + click_to_show: Option, + /// Toggle this annotation when clicking a data point whose `x` value is + /// `xclick` rather than the annotation's `x` value. + #[serde(rename = "xclick")] + x_click: Option, + /// Toggle this annotation when clicking a data point whose `y` value is + /// `yclick` rather than the annotation's `y` value. + #[serde(rename = "yclick")] + y_click: Option, + /// Sets text to appear when hovering over this annotation. If omitted or + /// blank, no hover label will appear. + #[serde(rename = "hovertext")] + hover_text: Option, + /// Label displayed on mouse hover. + #[serde(rename = "hoverlabel")] + hover_label: Option