use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::core::ids::PortId;
use super::port::PortKind;
fn is_false(v: &bool) -> bool {
!*v
}
fn edge_view_descriptor_is_default(value: &EdgeViewDescriptor) -> bool {
value.is_default()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EdgeKind {
Data,
Exec,
}
impl EdgeKind {
pub fn port_kind(self) -> PortKind {
match self {
Self::Data => PortKind::Data,
Self::Exec => PortKind::Exec,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EdgeRouteKind {
Straight,
Orthogonal,
Bezier,
SmoothStep,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Edge {
pub kind: EdgeKind,
pub from: PortId,
pub to: PortId,
#[serde(default, skip_serializing_if = "is_false")]
pub hidden: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub selectable: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub focusable: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub interaction_width: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deletable: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reconnectable: Option<EdgeReconnectable>,
#[serde(default)]
pub data: Value,
#[serde(default, skip_serializing_if = "edge_view_descriptor_is_default")]
pub view: EdgeViewDescriptor,
}
impl Edge {
pub fn new(kind: EdgeKind, from: PortId, to: PortId) -> Self {
Self {
kind,
from,
to,
hidden: false,
selectable: None,
focusable: None,
interaction_width: None,
deletable: None,
reconnectable: None,
data: Value::Null,
view: EdgeViewDescriptor::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct EdgeViewDescriptor {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub renderer_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label_anchor: Option<EdgeLabelAnchor>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_marker_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target_marker_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub style_token: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub route_kind: Option<EdgeRouteKind>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub hit_target_width: Option<f32>,
}
impl EdgeViewDescriptor {
pub fn new() -> Self {
Self::default()
}
pub fn with_renderer_key(mut self, renderer_key: impl Into<String>) -> Self {
self.renderer_key = Some(renderer_key.into());
self
}
pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn with_label_anchor(mut self, label_anchor: EdgeLabelAnchor) -> Self {
self.label_anchor = Some(label_anchor);
self
}
pub fn with_source_marker_key(mut self, source_marker_key: impl Into<String>) -> Self {
self.source_marker_key = Some(source_marker_key.into());
self
}
pub fn with_target_marker_key(mut self, target_marker_key: impl Into<String>) -> Self {
self.target_marker_key = Some(target_marker_key.into());
self
}
pub fn with_style_token(mut self, style_token: impl Into<String>) -> Self {
self.style_token = Some(style_token.into());
self
}
pub fn with_route_kind(mut self, route_kind: EdgeRouteKind) -> Self {
self.route_kind = Some(route_kind);
self
}
pub fn with_hit_target_width(mut self, hit_target_width: f32) -> Self {
self.hit_target_width = Some(hit_target_width);
self
}
pub fn is_default(&self) -> bool {
self == &Self::default()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EdgeLabelAnchor {
Source,
Center,
Target,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum EdgeReconnectable {
Bool(bool),
Endpoint(EdgeReconnectableEndpoint),
}
impl EdgeReconnectable {
pub fn allows_source(self) -> bool {
matches!(
self,
Self::Bool(true) | Self::Endpoint(EdgeReconnectableEndpoint::Source)
)
}
pub fn allows_target(self) -> bool {
matches!(
self,
Self::Bool(true) | Self::Endpoint(EdgeReconnectableEndpoint::Target)
)
}
pub fn endpoint_flags(self) -> (bool, bool) {
(self.allows_source(), self.allows_target())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EdgeReconnectableEndpoint {
Source,
Target,
}