Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support margins, margin_cluster_default, and margin_node_default. #38

Merged
merged 2 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## unreleased

* Support `margins` in `GraphvizAttrs`.
* Support `margin_cluster_default` in `GraphvizAttrs`.
* Support `margin_node_default` in `GraphvizAttrs`.
* Support `node_width_default` in `GraphvizAttrs`.
* Support `node_widths` in `GraphvizAttrs`.
* Support `node_height_default` in `GraphvizAttrs`.
Expand Down
90 changes: 87 additions & 3 deletions crate/model/src/common/graphviz_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
use serde::{Deserialize, Serialize};

pub use self::{
edge_constraints::EdgeConstraints, edge_dir::EdgeDir, edge_dirs::EdgeDirs,
edge_minlens::EdgeMinlens, fixed_size::FixedSize, node_heights::NodeHeights,
node_widths::NodeWidths, pack_mode::PackMode, pack_mode_flag::PackModeFlag, splines::Splines,
cluster_margin::ClusterMargin, edge_constraints::EdgeConstraints, edge_dir::EdgeDir,
edge_dirs::EdgeDirs, edge_minlens::EdgeMinlens, fixed_size::FixedSize, margin::Margin,
margins::Margins, node_heights::NodeHeights, node_margin::NodeMargin, node_widths::NodeWidths,
pack_mode::PackMode, pack_mode_flag::PackModeFlag, splines::Splines,
};

mod cluster_margin;
mod edge_constraints;
mod edge_dir;
mod edge_dirs;
mod edge_minlens;
mod fixed_size;
mod margin;
mod margins;
mod node_heights;
mod node_margin;
mod node_widths;
mod pack_mode;
mod pack_mode_flag;
Expand Down Expand Up @@ -69,6 +74,24 @@
///
/// [`minlen`]: https://graphviz.org/docs/attrs/minlen/
pub edge_minlens: EdgeMinlens,
/// The default value for each node's [`margin`], defaults to `0.11,0.055`.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub margin_cluster_default: ClusterMargin,
/// The default value for each cluster's [`margin`], defaults to `8.0`.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub margin_node_default: NodeMargin,
/// Each node or cluster's [`margin`].
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub margins: Margins,
/// Minimum / initial [`width`] for nodes, defaults to `0.3`.
///
/// If `fixedsize` is true, this will be the exact / maximum width for
Expand Down Expand Up @@ -197,6 +220,37 @@
self
}

/// Sets the default value for each node's [`margin`], defaults to
/// `0.11,0.055`.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn with_margin_cluster_default(mut self, margin_cluster_default: ClusterMargin) -> Self {
self.margin_cluster_default = margin_cluster_default;
self
}

Check warning on line 232 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L229-L232

Added lines #L229 - L232 were not covered by tests

/// Sets the default value for each cluster's [`margin`], defaults to `8.0`.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn with_margin_node_default(mut self, margin_node_default: NodeMargin) -> Self {
self.margin_node_default = margin_node_default;
self
}

Check warning on line 242 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L239-L242

Added lines #L239 - L242 were not covered by tests

/// Sets each node or cluster's [`margin`].
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn with_margins(mut self, margins: Margins) -> Self {
self.margins = margins;
self
}

Check warning on line 252 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L249-L252

Added lines #L249 - L252 were not covered by tests

/// Sets the minimum / initial [`width`] for nodes, defaults to `0.3`.
///
/// If `fixedsize` is true, this will be the exact / maximum width for
Expand Down Expand Up @@ -323,6 +377,33 @@
&self.edge_minlens
}

/// Returns the default value for each node's [`margin`].
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn margin_cluster_default(&self) -> ClusterMargin {
self.margin_cluster_default
}

Check warning on line 387 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L385-L387

Added lines #L385 - L387 were not covered by tests

/// Returns the default value for each cluster's [`margin`].
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn margin_node_default(&self) -> NodeMargin {
self.margin_node_default
}

Check warning on line 396 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L394-L396

Added lines #L394 - L396 were not covered by tests

/// Returns each node or cluster's [`margin`].
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
pub fn margins(&self) -> &Margins {
&self.margins
}

Check warning on line 405 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L403-L405

Added lines #L403 - L405 were not covered by tests

/// Returns the minimum / initial [`width`] for nodes.
///
/// If `fixedsize` is true, this will be the exact / maximum width for
Expand Down Expand Up @@ -385,6 +466,9 @@
edge_dirs: EdgeDirs::default(),
edge_minlen_default: 2,
edge_minlens: EdgeMinlens::default(),
margin_cluster_default: ClusterMargin::default(),
margin_node_default: NodeMargin::default(),
margins: Margins::default(),

Check warning on line 471 in crate/model/src/common/graphviz_attrs.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs.rs#L469-L471

Added lines #L469 - L471 were not covered by tests
node_width_default: 0.3,
node_widths: NodeWidths::default(),
node_height_default: 0.1,
Expand Down
61 changes: 61 additions & 0 deletions crate/model/src/common/graphviz_attrs/cluster_margin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::fmt;

use serde::{Deserialize, Serialize};

use crate::common::graphviz_attrs::Margin;

/// A node [`margin`], which specifies the space between the nodes in the
/// cluster and the cluster bounding box.
///
/// Defaults to `Margin::Same(8.0)`; Graphviz default: `8.0`.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]

Check warning on line 15 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L15

Added line #L15 was not covered by tests
#[serde(rename_all = "snake_case")]
pub struct ClusterMargin(pub Margin);

impl ClusterMargin {
/// Returns a new `ClusterMargin`.
pub fn new() -> Self {
Self::default()
}

Check warning on line 23 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L21-L23

Added lines #L21 - L23 were not covered by tests

/// Returns the inner `Margin`.
pub fn into_inner(self) -> Margin {
self.0
}

Check warning on line 28 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L26-L28

Added lines #L26 - L28 were not covered by tests
}

impl Default for ClusterMargin {
fn default() -> Self {
Self(Margin::Same(8.0))
}

Check warning on line 34 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L32-L34

Added lines #L32 - L34 were not covered by tests
}

impl From<Margin> for ClusterMargin {
fn from(margin: Margin) -> Self {
Self(margin)
}

Check warning on line 40 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L38-L40

Added lines #L38 - L40 were not covered by tests
}

impl std::ops::DerefMut for ClusterMargin {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}

Check warning on line 46 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L44-L46

Added lines #L44 - L46 were not covered by tests
}

impl std::ops::Deref for ClusterMargin {
type Target = Margin;

fn deref(&self) -> &Self::Target {
&self.0
}

Check warning on line 54 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L52-L54

Added lines #L52 - L54 were not covered by tests
}

impl fmt::Display for ClusterMargin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}

Check warning on line 60 in crate/model/src/common/graphviz_attrs/cluster_margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/cluster_margin.rs#L58-L60

Added lines #L58 - L60 were not covered by tests
}
78 changes: 78 additions & 0 deletions crate/model/src/common/graphviz_attrs/margin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::{fmt, fmt::Display, str::FromStr};

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

/// Node or cluster [`margin`]s.
///
/// May be a single float, or two floats separated by a comma.
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Margin {
/// Margins on both left/right and top/bottom are the same.
Same(f64),
/// Margins for left/right are different to top/bottom.
Different(f64, f64),
}

impl FromStr for Margin {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split_once(',') {
Some((margin_x, margin_y)) => {
let margin_x = margin_x.parse::<f64>().map_err(|_e| {
format!(
"Failed to parse `{margin_x}` as a margin. \
Please use a floating point number such as 0.5."
)
})?;
let margin_y = margin_y.parse::<f64>().map_err(|_e| {
format!(
"Failed to parse `{margin_y}` as a margin. \
Please use a floating point number such as 0.5."
)
})?;

Check warning on line 35 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L21-L35

Added lines #L21 - L35 were not covered by tests

Ok(Self::Different(margin_x, margin_y))

Check warning on line 37 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L37

Added line #L37 was not covered by tests
}
None => {
let margin = s.parse::<f64>().map_err(|_e| {
format!(
"Failed to parse `{s}` as a margin. \
Please use a floating point number such as 0.5."
)
})?;
Ok(Self::Same(margin))

Check warning on line 46 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L40-L46

Added lines #L40 - L46 were not covered by tests
}
}
}

Check warning on line 49 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L49

Added line #L49 was not covered by tests
}

impl Display for Margin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Margin::Same(margin) => margin.fmt(f),
Margin::Different(margin_x, margin_y) => write!(f, "{margin_x},{margin_y}"),

Check warning on line 56 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L53-L56

Added lines #L53 - L56 were not covered by tests
}
}

Check warning on line 58 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L58

Added line #L58 was not covered by tests
}

impl<'de> Deserialize<'de> for Margin {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}

Check warning on line 68 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L62-L68

Added lines #L62 - L68 were not covered by tests
}

impl Serialize for Margin {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}

Check warning on line 77 in crate/model/src/common/graphviz_attrs/margin.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margin.rs#L72-L77

Added lines #L72 - L77 were not covered by tests
}
64 changes: 64 additions & 0 deletions crate/model/src/common/graphviz_attrs/margins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use std::ops::{Deref, DerefMut};

use indexmap::IndexMap;
use serde::{Deserialize, Serialize};

use crate::common::{graphviz_attrs::Margin, NodeId};

/// GraphViz node or cluster margins. `IndexMap<NodeId, Margin>` newtype.
///
/// This is only used for GraphViz dot graphs, which sets the [`margin`]
/// attribute for the node / cluster.
///
/// If this is unset, nodes will use the default [`NodeMargin`], and clusters
/// will use the default [`ClusterMargin`].
///
/// [`margin`]: https://graphviz.org/docs/attrs/margin/
/// [`NodeMargin`]: crate::common::graphviz_attrs::NodeMargin
/// [`ClusterMargin`]: crate::common::graphviz_attrs::ClusterMargin
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]

Check warning on line 19 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L19

Added line #L19 was not covered by tests
pub struct Margins(IndexMap<NodeId, Margin>);

impl Margins {
/// Returns a new `Margins` map.
pub fn new() -> Self {
Self::default()
}

Check warning on line 26 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L24-L26

Added lines #L24 - L26 were not covered by tests

/// Returns a new `Margins` map with the given preallocated
/// capacity.
pub fn with_capacity(capacity: usize) -> Self {
Self(IndexMap::with_capacity(capacity))
}

Check warning on line 32 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L30-L32

Added lines #L30 - L32 were not covered by tests

/// Returns the underlying map.
pub fn into_inner(self) -> IndexMap<NodeId, Margin> {
self.0
}

Check warning on line 37 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L35-L37

Added lines #L35 - L37 were not covered by tests
}

impl Deref for Margins {
type Target = IndexMap<NodeId, Margin>;

fn deref(&self) -> &Self::Target {
&self.0
}

Check warning on line 45 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L43-L45

Added lines #L43 - L45 were not covered by tests
}

impl DerefMut for Margins {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}

Check warning on line 51 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L49-L51

Added lines #L49 - L51 were not covered by tests
}

impl From<IndexMap<NodeId, Margin>> for Margins {
fn from(inner: IndexMap<NodeId, Margin>) -> Self {
Self(inner)
}

Check warning on line 57 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L55-L57

Added lines #L55 - L57 were not covered by tests
}

impl FromIterator<(NodeId, Margin)> for Margins {
fn from_iter<I: IntoIterator<Item = (NodeId, Margin)>>(iter: I) -> Self {
Self(IndexMap::from_iter(iter))
}

Check warning on line 63 in crate/model/src/common/graphviz_attrs/margins.rs

View check run for this annotation

Codecov / codecov/patch

crate/model/src/common/graphviz_attrs/margins.rs#L61-L63

Added lines #L61 - L63 were not covered by tests
}
Loading