use std::any::{Any, TypeId};
use std::cell::Cell;
use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Weak};
use crate::{color, Color, Colorable, Point, Positionable, Scalar, Ui, UiCell, widget};
pub use self::node::{Node, SocketLayout, SocketSide};
pub mod node;
pub trait NodeId: 'static + Copy + Clone + PartialEq + Eq + Hash + Send {}
impl<T> NodeId for T where T: 'static + Copy + Clone + PartialEq + Eq + Hash + Send {}
#[derive(Clone, Debug, PartialEq)]
pub struct Layout<NI>
where
NI: Eq + Hash,
{
map: HashMap<NI, Point>,
}
impl<NI> Deref for Layout<NI>
where
NI: NodeId,
{
type Target = HashMap<NI, Point>;
fn deref(&self) -> &Self::Target {
&self.map
}
}
impl<NI> DerefMut for Layout<NI>
where
NI: NodeId,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.map
}
}
#[derive(Clone, Debug, WidgetCommon_)]
pub struct Graph<'a, N, E>
where
N: Iterator,
N::Item: NodeId,
E: Iterator<Item=(NodeSocket<N::Item>, NodeSocket<N::Item>)>,
{
#[carbide(common_builder)]
pub common: widget::CommonBuilder,
pub style: Style,
pub nodes: N,
pub edges: E,
pub layout: &'a Layout<N::Item>,
}
#[derive(Copy, Clone, Debug, Default, PartialEq, WidgetStyle_)]
pub struct Style {
#[carbide(default = "color::TRANSPARENT")]
pub background_color: Option<Color>,
}
widget_ids! {
struct Ids {
background,
}
}
pub struct State<NI>
where
NI: NodeId,
{
ids: Ids,
shared: Arc<Mutex<Shared<NI>>>,
}
struct Shared<NI>
where
NI: NodeId,
{
events: VecDeque<Event<NI>>,
nodes: HashMap<NI, NodeInner>,
node_ids: Vec<NI>,
edges: Vec<(NodeSocket<NI>, NodeSocket<NI>)>,
widget_id_map: WidgetIdMap<NI>,
}
#[derive(Copy, Clone, Debug)]
struct SocketLayouts {
input: SocketLayout,
output: SocketLayout,
}
#[derive(Default)]
struct TypeWidgetIds {
next_index: usize,
widget_ids: Vec<widget::Id>,
}
impl TypeWidgetIds {
fn next_id(&mut self, generator: &mut widget::old::id::Generator) -> widget::Id {
loop {
match self.widget_ids.get(self.next_index).map(|&id| id) {
None => self.widget_ids.push(generator.next()),
Some(id) => {
self.next_index += 1;
break id;
}
}
}
}
}
#[derive(Default)]
struct WidgetIdMap<NI>
where
NI: NodeId,
{
type_widget_ids: HashMap<TypeId, TypeWidgetIds>,
node_widget_ids: HashMap<NI, widget::Id>,
}
impl<NI> WidgetIdMap<NI>
where
NI: NodeId,
{
fn reset_indices(&mut self) {
for type_widget_ids in self.type_widget_ids.values_mut() {
type_widget_ids.next_index = 0;
}
}
fn clear_node_mappings(&mut self) {
self.node_widget_ids.clear();
}
fn next_id_for_node<T>(&mut self, node_id: NI, generator: &mut widget::old::id::Generator) -> widget::Id
where
T: Any,
{
let type_id = TypeId::of::<T>();
let type_widget_ids = self.type_widget_ids.entry(type_id).or_insert_with(TypeWidgetIds::default);
let widget_id = type_widget_ids.next_id(generator);
self.node_widget_ids.insert(node_id, widget_id);
widget_id
}
fn next_id_for_edge<T>(&mut self, generator: &mut widget::old::id::Generator) -> widget::Id
where
T: Any,
{
let type_id = TypeId::of::<T>();
let type_widget_ids = self.type_widget_ids.entry(type_id).or_insert_with(TypeWidgetIds::default);
let widget_id = type_widget_ids.next_id(generator);
widget_id
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Event<NI> {
Node(NodeEvent<NI>),
Edge(EdgeEvent<NI>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct NodeSocket<NI> {
pub id: NI,
pub socket_index: usize,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum NodeEvent<NI> {
Remove(NI),
Dragged {
node_id: NI,
from: Point,
to: Point,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum EdgeEvent<NI> {
AddStart(NodeSocket<NI>),
Add {
start: NodeSocket<NI>,
end: NodeSocket<NI>,
},
Cancelled(NodeSocket<NI>),
Remove {
start: NodeSocket<NI>,
end: NodeSocket<NI>,
},
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Camera {
point: Point,
zoom: Scalar,
}
pub struct Session<NI: NodeId> {
graph_id: widget::Id,
shared: Weak<Mutex<Shared<NI>>>,
}
pub struct SessionEvents<NI: NodeId> {
session: Session<NI>,
}
pub struct SessionNodes<NI: NodeId> {
session: Session<NI>,
}
pub struct SessionEdges<NI: NodeId> {
session: Session<NI>,
}
pub struct Events<'a, NI: NodeId> {
shared: Arc<Mutex<Shared<NI>>>,
lifetime: PhantomData<&'a ()>,
}
pub struct Nodes<'a, NI: 'a + NodeId> {
index: usize,
shared: Arc<Mutex<Shared<NI>>>,
graph_id: widget::Id,
lifetime: PhantomData<&'a NI>,
}
#[derive(Copy, Clone)]
struct NodeInner {
point: Point,
}
pub struct NodeContext<'a, NI: 'a + NodeId> {
node_id: NI,
point: Point,
graph_id: widget::Id,
shared: Arc<Mutex<Shared<NI>>>,
lifetime: PhantomData<&'a NI>,
}
pub struct NodeWidget<'a, NI: 'a + NodeId, W> {
node: NodeContext<'a, NI>,
widget: W,
widget_id: Cell<Option<widget::Id>>,
}
pub struct Edges<'a, NI: 'a + NodeId> {
index: usize,
shared: Arc<Mutex<Shared<NI>>>,
graph_id: widget::Id,
lifetime: PhantomData<&'a ()>,
}
pub struct Edge<'a, NI: NodeId> {
graph_id: widget::Id,
shared: Arc<Mutex<Shared<NI>>>,
start: NodeSocket<NI>,
end: NodeSocket<NI>,
lifetime: PhantomData<&'a ()>,
}
pub struct EdgeWidget<'a, NI: 'a + NodeId, W> {
edge: Edge<'a, NI>,
widget: W,
widget_id: Cell<Option<widget::Id>>,
}
impl<NI> From<HashMap<NI, Point>> for Layout<NI>
where
NI: NodeId,
{
fn from(map: HashMap<NI, Point>) -> Self {
Layout { map }
}
}
impl<NI> Into<HashMap<NI, Point>> for Layout<NI>
where
NI: NodeId,
{
fn into(self) -> HashMap<NI, Point> {
let Layout { map } = self;
map
}
}
impl<NI> SessionEvents<NI>
where
NI: NodeId,
{
pub fn events(&self) -> Events<NI> {
let shared = self.session.shared.upgrade().expect("failed to access `Shared` state");
Events { shared, lifetime: PhantomData }
}
pub fn next(self) -> SessionNodes<NI> {
let SessionEvents { session } = self;
SessionNodes { session }
}
}
impl<'a, NI> Iterator for Events<'a, NI>
where
NI: NodeId,
{
type Item = Event<NI>;
fn next(&mut self) -> Option<Self::Item> {
self.shared.lock()
.ok()
.and_then(|mut guard| guard.events.pop_front())
}
}
impl<NI> SessionNodes<NI>
where
NI: NodeId,
{
pub fn nodes(&mut self) -> Nodes<NI> {
let graph_id = self.session.graph_id;
let shared = self.session.shared.upgrade().expect("failed to access `Shared` state");
Nodes { index: 0, shared, graph_id, lifetime: PhantomData }
}
pub fn next(self) -> SessionEdges<NI> {
let SessionNodes { session } = self;
SessionEdges { session }
}
}
impl<'a, NI> Iterator for Nodes<'a, NI>
where
NI: NodeId,
{
type Item = NodeContext<'a, NI>;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
self.index += 1;
self.shared.lock()
.ok()
.and_then(|guard| {
guard.node_ids
.get(index)
.and_then(|&id| guard.nodes.get(&id).map(|&inner| (id, inner)))
})
.map(|(node_id, NodeInner { point })| {
NodeContext {
node_id,
point,
graph_id: self.graph_id,
shared: self.shared.clone(),
lifetime: PhantomData,
}
})
}
}
impl<NI> SessionEdges<NI>
where
NI: NodeId,
{
pub fn edges(&mut self) -> Edges<NI> {
let graph_id = self.session.graph_id;
let shared = self.session.shared.upgrade().expect("failed to access `Shared` state");
Edges { index: 0, shared, graph_id, lifetime: PhantomData }
}
}
impl<'a, NI> Iterator for Edges<'a, NI>
where
NI: NodeId,
{
type Item = Edge<'a, NI>;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
self.index += 1;
self.shared.lock()
.ok()
.and_then(|guard| {
guard.edges.get(index).map(|&(start, end)| {
Edge {
graph_id: self.graph_id,
shared: self.shared.clone(),
start: start,
end: end,
lifetime: PhantomData,
}
})
})
}
}
impl<'a, NI> NodeContext<'a, NI>
where
NI: NodeId,
{
pub fn node_id(&self) -> NI {
self.node_id
}
pub fn point(&self) -> Point {
self.point
}
pub fn widget<W>(self, widget: W) -> NodeWidget<'a, NI, W> {
NodeWidget {
node: self,
widget,
widget_id: Cell::new(None),
}
}
}
impl<'a, NI, W> Deref for NodeWidget<'a, NI, W>
where
NI: NodeId,
{
type Target = NodeContext<'a, NI>;
fn deref(&self) -> &Self::Target {
&self.node
}
}
impl<'a, NI> Edge<'a, NI>
where
NI: NodeId,
{
pub fn start(&self) -> NodeSocket<NI> {
self.start
}
pub fn end(&self) -> NodeSocket<NI> {
self.end
}
pub fn sockets(&self) -> (NodeSocket<NI>, NodeSocket<NI>) {
(self.start, self.end)
}
pub fn widget<W>(self, widget: W) -> EdgeWidget<'a, NI, W> {
EdgeWidget {
edge: self,
widget,
widget_id: Cell::new(None),
}
}
}
impl<'a, N, E> Graph<'a, N, E>
where
N: Iterator,
N::Item: NodeId,
E: Iterator<Item=(NodeSocket<N::Item>, NodeSocket<N::Item>)>,
{
pub fn new<NI, EI>(nodes: NI, edges: EI, layout: &'a Layout<NI::Item>) -> Self
where
NI: IntoIterator<IntoIter=N, Item=N::Item>,
EI: IntoIterator<IntoIter=E, Item=(NodeSocket<N::Item>, NodeSocket<N::Item>)>,
{
Graph {
common: widget::CommonBuilder::default(),
style: Style::default(),
nodes: nodes.into_iter(),
edges: edges.into_iter(),
layout: layout,
}
}
pub fn background_color(mut self, color: Color) -> Self {
self.style.background_color = Some(color);
self
}
}