-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from azriel91/feature/margins
- Loading branch information
Showing
8 changed files
with
401 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)] | ||
#[serde(rename_all = "snake_case")] | ||
pub struct ClusterMargin(pub Margin); | ||
|
||
impl ClusterMargin { | ||
/// Returns a new `ClusterMargin`. | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Returns the inner `Margin`. | ||
pub fn into_inner(self) -> Margin { | ||
self.0 | ||
} | ||
} | ||
|
||
impl Default for ClusterMargin { | ||
fn default() -> Self { | ||
Self(Margin::Same(8.0)) | ||
} | ||
} | ||
|
||
impl From<Margin> for ClusterMargin { | ||
fn from(margin: Margin) -> Self { | ||
Self(margin) | ||
} | ||
} | ||
|
||
impl std::ops::DerefMut for ClusterMargin { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.0 | ||
} | ||
} | ||
|
||
impl std::ops::Deref for ClusterMargin { | ||
type Target = Margin; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl fmt::Display for ClusterMargin { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
self.0.fmt(f) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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." | ||
) | ||
})?; | ||
|
||
Ok(Self::Different(margin_x, margin_y)) | ||
} | ||
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)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
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}"), | ||
} | ||
} | ||
} | ||
|
||
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) | ||
} | ||
} | ||
|
||
impl Serialize for Margin { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
serializer.serialize_str(&self.to_string()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)] | ||
pub struct Margins(IndexMap<NodeId, Margin>); | ||
|
||
impl Margins { | ||
/// Returns a new `Margins` map. | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
|
||
/// Returns a new `Margins` map with the given preallocated | ||
/// capacity. | ||
pub fn with_capacity(capacity: usize) -> Self { | ||
Self(IndexMap::with_capacity(capacity)) | ||
} | ||
|
||
/// Returns the underlying map. | ||
pub fn into_inner(self) -> IndexMap<NodeId, Margin> { | ||
self.0 | ||
} | ||
} | ||
|
||
impl Deref for Margins { | ||
type Target = IndexMap<NodeId, Margin>; | ||
|
||
fn deref(&self) -> &Self::Target { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl DerefMut for Margins { | ||
fn deref_mut(&mut self) -> &mut Self::Target { | ||
&mut self.0 | ||
} | ||
} | ||
|
||
impl From<IndexMap<NodeId, Margin>> for Margins { | ||
fn from(inner: IndexMap<NodeId, Margin>) -> Self { | ||
Self(inner) | ||
} | ||
} | ||
|
||
impl FromIterator<(NodeId, Margin)> for Margins { | ||
fn from_iter<I: IntoIterator<Item = (NodeId, Margin)>>(iter: I) -> Self { | ||
Self(IndexMap::from_iter(iter)) | ||
} | ||
} |
Oops, something went wrong.