use std::fmt::Debug;
use std::marker::PhantomData;
use egui::{Color32, Pos2};
use petgraph::{
stable_graph::{DefaultIx, IndexType, NodeIndex},
Directed, EdgeType,
};
use serde::{Deserialize, Serialize};
use crate::{DefaultNodeShape, DisplayNode};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeProps<N>
where
N: Clone,
{
pub payload: N,
pub label: String,
pub selected: bool,
pub dragged: bool,
pub hovered: bool,
color: Option<Color32>,
location: Pos2,
}
impl<N> NodeProps<N>
where
N: Clone,
{
pub fn location(&self) -> Pos2 {
self.location
}
pub fn color(&self) -> Option<Color32> {
self.color
}
}
#[derive(Serialize, Deserialize)]
pub struct Node<N, E, Ty = Directed, Ix = DefaultIx, D = DefaultNodeShape>
where
N: Clone,
E: Clone,
Ty: EdgeType,
Ix: IndexType,
D: DisplayNode<N, E, Ty, Ix>,
{
id: Option<NodeIndex<Ix>>,
props: NodeProps<N>,
display: D,
_marker: PhantomData<(E, Ty)>,
}
#[allow(clippy::missing_fields_in_debug)] impl<N, E, Ty, Ix, D> Debug for Node<N, E, Ty, Ix, D>
where
N: Clone,
E: Clone,
Ty: EdgeType,
Ix: IndexType,
D: DisplayNode<N, E, Ty, Ix>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Node").field("id", &self.id).finish()
}
}
impl<N, E, Ty, Ix, D> Clone for Node<N, E, Ty, Ix, D>
where
N: Clone,
E: Clone,
Ty: EdgeType,
Ix: IndexType,
D: DisplayNode<N, E, Ty, Ix>,
{
fn clone(&self) -> Self {
let idx = self.id().index();
Self {
id: Some(NodeIndex::new(idx)),
props: self.props.clone(),
display: self.display.clone(),
_marker: PhantomData,
}
}
}
impl<N, E, Ty, Ix, D> Node<N, E, Ty, Ix, D>
where
N: Clone,
E: Clone,
Ty: EdgeType,
Ix: IndexType,
D: DisplayNode<N, E, Ty, Ix>,
{
pub fn new(payload: N) -> Self {
let props = NodeProps {
payload,
location: Pos2::default(),
color: Option::default(),
label: String::default(),
selected: bool::default(),
dragged: bool::default(),
hovered: bool::default(),
};
Node::new_with_props(props)
}
pub fn new_with_props(props: NodeProps<N>) -> Self {
let display = D::from(props.clone());
Self {
props,
display,
id: Option::default(),
_marker: PhantomData,
}
}
pub fn props(&self) -> &NodeProps<N> {
&self.props
}
pub fn display(&self) -> &D {
&self.display
}
pub fn display_mut(&mut self) -> &mut D {
&mut self.display
}
#[allow(clippy::missing_panics_doc)] pub fn id(&self) -> NodeIndex<Ix> {
self.id.unwrap()
}
pub(crate) fn set_id(&mut self, id: NodeIndex<Ix>) {
self.id = Some(id);
}
pub fn payload(&self) -> &N {
&self.props.payload
}
pub fn payload_mut(&mut self) -> &mut N {
&mut self.props.payload
}
pub fn color(&self) -> Option<Color32> {
self.props.color()
}
pub fn set_color(&mut self, color: Color32) {
self.props.color = Some(color);
}
pub fn location(&self) -> Pos2 {
self.props.location()
}
pub fn set_location(&mut self, loc: Pos2) {
self.props.location = loc;
}
pub fn selected(&self) -> bool {
self.props.selected
}
pub fn set_selected(&mut self, selected: bool) {
self.props.selected = selected;
}
pub fn dragged(&self) -> bool {
self.props.dragged
}
pub fn set_dragged(&mut self, dragged: bool) {
self.props.dragged = dragged;
}
pub fn hovered(&self) -> bool {
self.props.hovered
}
pub fn set_hovered(&mut self, hovered: bool) {
self.props.hovered = hovered;
}
pub fn label(&self) -> String {
self.props.label.clone()
}
pub fn set_label(&mut self, label: String) {
self.props.label = label;
}
}