1use std::any::{Any, TypeId};
4use std::cell::Cell;
5use std::collections::{HashMap, VecDeque};
6use std::hash::Hash;
7use std::marker::PhantomData;
8use std::ops::{Deref, DerefMut};
9use std::sync::{Arc, Mutex, Weak};
10use utils::{iter_diff, IterDiff};
11use {color, widget, Color, Colorable, Point, Positionable, Scalar, Ui, UiCell, Widget};
12
13pub use self::node::{Node, SocketLayout, SocketSide};
14
15pub mod node;
16
17pub trait NodeId: 'static + Copy + Clone + PartialEq + Eq + Hash + Send {}
21impl<T> NodeId for T where T: 'static + Copy + Clone + PartialEq + Eq + Hash + Send {}
22
23#[derive(Clone, Debug, PartialEq)]
29pub struct Layout<NI>
30where
31 NI: Eq + Hash,
32{
33 map: HashMap<NI, Point>,
34}
35
36impl<NI> Deref for Layout<NI>
37where
38 NI: NodeId,
39{
40 type Target = HashMap<NI, Point>;
41 fn deref(&self) -> &Self::Target {
42 &self.map
43 }
44}
45
46impl<NI> DerefMut for Layout<NI>
47where
48 NI: NodeId,
49{
50 fn deref_mut(&mut self) -> &mut Self::Target {
51 &mut self.map
52 }
53}
54
55#[derive(Clone, Debug, WidgetCommon_)]
57pub struct Graph<'a, N, E>
58where
59 N: Iterator,
60 N::Item: NodeId,
61 E: Iterator<Item = (NodeSocket<N::Item>, NodeSocket<N::Item>)>,
62{
63 #[conrod(common_builder)]
65 pub common: widget::CommonBuilder,
66 pub style: Style,
68 pub nodes: N,
70 pub edges: E,
72 pub layout: &'a Layout<N::Item>,
74}
75
76#[derive(Copy, Clone, Debug, Default, PartialEq, WidgetStyle_)]
78pub struct Style {
79 #[conrod(default = "color::TRANSPARENT")]
81 pub background_color: Option<Color>,
82}
83
84widget_ids! {
85 struct Ids {
86 background,
88 }
89}
90
91pub struct State<NI>
93where
94 NI: NodeId,
95{
96 ids: Ids,
97 shared: Arc<Mutex<Shared<NI>>>,
98}
99
100struct Shared<NI>
102where
103 NI: NodeId,
104{
105 events: VecDeque<Event<NI>>,
108 nodes: HashMap<NI, NodeInner>,
110 node_ids: Vec<NI>,
112 edges: Vec<(NodeSocket<NI>, NodeSocket<NI>)>,
114 widget_id_map: WidgetIdMap<NI>,
116}
117
118#[derive(Copy, Clone, Debug)]
120struct SocketLayouts {
121 input: SocketLayout,
122 output: SocketLayout,
123}
124
125#[derive(Default)]
127struct TypeWidgetIds {
128 next_index: usize,
130 widget_ids: Vec<widget::Id>,
132}
133
134impl TypeWidgetIds {
135 fn next_id(&mut self, generator: &mut widget::id::Generator) -> widget::Id {
140 loop {
141 match self.widget_ids.get(self.next_index).map(|&id| id) {
142 None => self.widget_ids.push(generator.next()),
143 Some(id) => {
144 self.next_index += 1;
145 break id;
146 }
147 }
148 }
149 }
150}
151
152#[derive(Default)]
154struct WidgetIdMap<NI>
155where
156 NI: NodeId,
157{
158 type_widget_ids: HashMap<TypeId, TypeWidgetIds>,
160 node_widget_ids: HashMap<NI, widget::Id>,
165}
166
167impl<NI> WidgetIdMap<NI>
168where
169 NI: NodeId,
170{
171 fn reset_indices(&mut self) {
177 for type_widget_ids in self.type_widget_ids.values_mut() {
178 type_widget_ids.next_index = 0;
179 }
180 }
181
182 fn clear_node_mappings(&mut self) {
185 self.node_widget_ids.clear();
186 }
187
188 fn next_id_for_node<T>(
193 &mut self,
194 node_id: NI,
195 generator: &mut widget::id::Generator,
196 ) -> widget::Id
197 where
198 T: Any,
199 {
200 let type_id = TypeId::of::<T>();
201 let type_widget_ids = self
202 .type_widget_ids
203 .entry(type_id)
204 .or_insert_with(TypeWidgetIds::default);
205 let widget_id = type_widget_ids.next_id(generator);
206 self.node_widget_ids.insert(node_id, widget_id);
207 widget_id
208 }
209
210 fn next_id_for_edge<T>(&mut self, generator: &mut widget::id::Generator) -> widget::Id
215 where
216 T: Any,
217 {
218 let type_id = TypeId::of::<T>();
219 let type_widget_ids = self
220 .type_widget_ids
221 .entry(type_id)
222 .or_insert_with(TypeWidgetIds::default);
223 let widget_id = type_widget_ids.next_id(generator);
224 widget_id
225 }
226}
227
228#[derive(Clone, Debug, PartialEq)]
235pub enum Event<NI> {
236 Node(NodeEvent<NI>),
238 Edge(EdgeEvent<NI>),
240}
241
242#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
248pub struct NodeSocket<NI> {
249 pub id: NI,
251 pub socket_index: usize,
255}
256
257#[derive(Copy, Clone, Debug, PartialEq)]
259pub enum NodeEvent<NI> {
260 Remove(NI),
262 Dragged {
264 node_id: NI,
266 from: Point,
268 to: Point,
270 },
271}
272
273#[derive(Copy, Clone, Debug, PartialEq, Eq)]
275#[allow(missing_docs)]
276pub enum EdgeEvent<NI> {
277 AddStart(NodeSocket<NI>),
280 Add {
282 start: NodeSocket<NI>,
283 end: NodeSocket<NI>,
284 },
285 Cancelled(NodeSocket<NI>),
287 Remove {
289 start: NodeSocket<NI>,
290 end: NodeSocket<NI>,
291 },
292}
293
294#[derive(Copy, Clone, Debug, Default, PartialEq)]
298pub struct Camera {
299 point: Point,
303 zoom: Scalar,
311}
312
313pub struct Session<NI: NodeId> {
324 graph_id: widget::Id,
326 shared: Weak<Mutex<Shared<NI>>>,
328}
329
330pub struct SessionEvents<NI: NodeId> {
332 session: Session<NI>,
333}
334
335pub struct SessionNodes<NI: NodeId> {
337 session: Session<NI>,
338}
339
340pub struct SessionEdges<NI: NodeId> {
342 session: Session<NI>,
343}
344
345pub struct Events<'a, NI: NodeId> {
347 shared: Arc<Mutex<Shared<NI>>>,
348 lifetime: PhantomData<&'a ()>,
350}
351
352pub struct Nodes<'a, NI: 'a + NodeId> {
356 index: usize,
358 shared: Arc<Mutex<Shared<NI>>>,
359 graph_id: widget::Id,
361 lifetime: PhantomData<&'a NI>,
363}
364
365#[derive(Copy, Clone)]
367struct NodeInner {
368 point: Point,
369}
370
371pub struct NodeContext<'a, NI: 'a + NodeId> {
379 node_id: NI,
380 point: Point,
381 graph_id: widget::Id,
383 shared: Arc<Mutex<Shared<NI>>>,
384 lifetime: PhantomData<&'a NI>,
386}
387
388pub struct NodeWidget<'a, NI: 'a + NodeId, W> {
393 node: NodeContext<'a, NI>,
394 widget: W,
395 widget_id: Cell<Option<widget::Id>>,
397}
398
399pub struct Edges<'a, NI: 'a + NodeId> {
403 index: usize,
405 shared: Arc<Mutex<Shared<NI>>>,
406 graph_id: widget::Id,
408 lifetime: PhantomData<&'a ()>,
410}
411
412pub struct Edge<'a, NI: NodeId> {
416 graph_id: widget::Id,
418 shared: Arc<Mutex<Shared<NI>>>,
420 start: NodeSocket<NI>,
422 end: NodeSocket<NI>,
424 lifetime: PhantomData<&'a ()>,
426}
427
428pub struct EdgeWidget<'a, NI: 'a + NodeId, W> {
433 edge: Edge<'a, NI>,
434 widget: W,
435 widget_id: Cell<Option<widget::Id>>,
437}
438
439impl<NI> From<HashMap<NI, Point>> for Layout<NI>
454where
455 NI: NodeId,
456{
457 fn from(map: HashMap<NI, Point>) -> Self {
458 Layout { map }
459 }
460}
461
462impl<NI> Into<HashMap<NI, Point>> for Layout<NI>
463where
464 NI: NodeId,
465{
466 fn into(self) -> HashMap<NI, Point> {
467 let Layout { map } = self;
468 map
469 }
470}
471
472impl<NI> SessionEvents<NI>
473where
474 NI: NodeId,
475{
476 pub fn events(&self) -> Events<NI> {
478 let shared = self
479 .session
480 .shared
481 .upgrade()
482 .expect("failed to access `Shared` state");
483 Events {
484 shared,
485 lifetime: PhantomData,
486 }
487 }
488
489 pub fn next(self) -> SessionNodes<NI> {
491 let SessionEvents { session } = self;
492 SessionNodes { session }
493 }
494}
495
496impl<'a, NI> Iterator for Events<'a, NI>
497where
498 NI: NodeId,
499{
500 type Item = Event<NI>;
501 fn next(&mut self) -> Option<Self::Item> {
502 self.shared
503 .lock()
504 .ok()
505 .and_then(|mut guard| guard.events.pop_front())
506 }
507}
508
509impl<NI> SessionNodes<NI>
510where
511 NI: NodeId,
512{
513 pub fn nodes(&mut self) -> Nodes<NI> {
515 let graph_id = self.session.graph_id;
516 let shared = self
517 .session
518 .shared
519 .upgrade()
520 .expect("failed to access `Shared` state");
521 Nodes {
522 index: 0,
523 shared,
524 graph_id,
525 lifetime: PhantomData,
526 }
527 }
528
529 pub fn next(self) -> SessionEdges<NI> {
531 let SessionNodes { session } = self;
532 SessionEdges { session }
533 }
534}
535
536impl<'a, NI> Iterator for Nodes<'a, NI>
537where
538 NI: NodeId,
539{
540 type Item = NodeContext<'a, NI>;
541 fn next(&mut self) -> Option<Self::Item> {
542 let index = self.index;
543 self.index += 1;
544 self.shared
545 .lock()
546 .ok()
547 .and_then(|guard| {
548 guard
549 .node_ids
550 .get(index)
551 .and_then(|&id| guard.nodes.get(&id).map(|&inner| (id, inner)))
552 })
553 .map(|(node_id, NodeInner { point })| NodeContext {
554 node_id,
555 point,
556 graph_id: self.graph_id,
557 shared: self.shared.clone(),
558 lifetime: PhantomData,
559 })
560 }
561}
562
563impl<NI> SessionEdges<NI>
564where
565 NI: NodeId,
566{
567 pub fn edges(&mut self) -> Edges<NI> {
569 let graph_id = self.session.graph_id;
570 let shared = self
571 .session
572 .shared
573 .upgrade()
574 .expect("failed to access `Shared` state");
575 Edges {
576 index: 0,
577 shared,
578 graph_id,
579 lifetime: PhantomData,
580 }
581 }
582}
583
584impl<'a, NI> Iterator for Edges<'a, NI>
585where
586 NI: NodeId,
587{
588 type Item = Edge<'a, NI>;
589 fn next(&mut self) -> Option<Self::Item> {
590 let index = self.index;
591 self.index += 1;
592 self.shared.lock().ok().and_then(|guard| {
593 guard.edges.get(index).map(|&(start, end)| Edge {
594 graph_id: self.graph_id,
595 shared: self.shared.clone(),
596 start: start,
597 end: end,
598 lifetime: PhantomData,
599 })
600 })
601 }
602}
603
604impl<'a, NI> NodeContext<'a, NI>
605where
606 NI: NodeId,
607{
608 pub fn node_id(&self) -> NI {
610 self.node_id
611 }
612
613 pub fn point(&self) -> Point {
615 self.point
616 }
617
618 pub fn widget<W>(self, widget: W) -> NodeWidget<'a, NI, W> {
620 NodeWidget {
621 node: self,
622 widget,
623 widget_id: Cell::new(None),
624 }
625 }
626}
627
628impl<'a, NI, W> NodeWidget<'a, NI, W>
629where
630 NI: NodeId,
631 W: 'static + Widget,
632{
633 pub fn widget_id(&self, ui: &mut UiCell) -> widget::Id {
635 match self.widget_id.get() {
636 Some(id) => id,
637 None => {
638 let mut shared = self.node.shared.lock().unwrap();
640 let id = shared
641 .widget_id_map
642 .next_id_for_node::<W>(self.node_id, &mut ui.widget_id_generator());
643 self.widget_id.set(Some(id));
644 id
645 }
646 }
647 }
648
649 pub fn map<M>(self, map: M) -> Self
651 where
652 M: FnOnce(W) -> W,
653 {
654 let NodeWidget {
655 node,
656 mut widget,
657 widget_id,
658 } = self;
659 widget = map(widget);
660 NodeWidget {
661 node,
662 widget,
663 widget_id,
664 }
665 }
666
667 pub fn set(self, ui: &mut UiCell) -> W::Event {
669 let widget_id = self.widget_id(ui);
670 let NodeWidget { node, widget, .. } = self;
671 widget
672 .xy_relative_to(node.graph_id, node.point)
673 .parent(node.graph_id)
674 .set(widget_id, ui)
675 }
676}
677
678impl<'a, NI, W> Deref for NodeWidget<'a, NI, W>
679where
680 NI: NodeId,
681{
682 type Target = NodeContext<'a, NI>;
683 fn deref(&self) -> &Self::Target {
684 &self.node
685 }
686}
687
688impl<'a, NI> Edge<'a, NI>
689where
690 NI: NodeId,
691{
692 pub fn start(&self) -> NodeSocket<NI> {
696 self.start
697 }
698
699 pub fn end(&self) -> NodeSocket<NI> {
703 self.end
704 }
705
706 pub fn sockets(&self) -> (NodeSocket<NI>, NodeSocket<NI>) {
708 (self.start, self.end)
709 }
710
711 pub fn widget<W>(self, widget: W) -> EdgeWidget<'a, NI, W> {
713 EdgeWidget {
714 edge: self,
715 widget,
716 widget_id: Cell::new(None),
717 }
718 }
719}
720
721pub fn node_widget_id<NI>(node_id: NI, graph_id: widget::Id, ui: &Ui) -> Option<widget::Id>
730where
731 NI: NodeId,
732{
733 ui.widget_graph()
734 .widget(graph_id)
735 .and_then(|container| container.state_and_style::<State<NI>, Style>())
736 .and_then(|unique| {
737 let shared = unique.state.shared.lock().unwrap();
738 shared
739 .widget_id_map
740 .node_widget_ids
741 .get(&node_id)
742 .map(|&id| id)
743 })
744}
745
746pub fn edge_node_widget_ids<NI>(edge: &Edge<NI>, ui: &Ui) -> (widget::Id, widget::Id)
755where
756 NI: NodeId,
757{
758 ui.widget_graph()
759 .widget(edge.graph_id)
760 .and_then(|container| container.state_and_style::<State<NI>, Style>())
761 .map(|unique| {
762 let shared = unique.state.shared.lock().unwrap();
763 let a = shared
764 .widget_id_map
765 .node_widget_ids
766 .get(&edge.start.id)
767 .map(|&id| id);
768 let b = shared
769 .widget_id_map
770 .node_widget_ids
771 .get(&edge.end.id)
772 .map(|&id| id);
773 (
774 a.expect("no `widget::Id` for start node"),
775 b.expect("no `widget::Id` for end node"),
776 )
777 })
778 .expect("no graph associated with edge's `graph_id` was found")
779}
780
781impl<'a, NI, W> EdgeWidget<'a, NI, W>
782where
783 NI: NodeId,
784 W: 'static + Widget,
785{
786 pub fn widget_id(&self, ui: &mut UiCell) -> widget::Id {
788 match self.widget_id.get() {
789 Some(id) => id,
790 None => {
791 let mut shared = self.edge.shared.lock().unwrap();
793 let id = shared
794 .widget_id_map
795 .next_id_for_edge::<W>(&mut ui.widget_id_generator());
796 self.widget_id.set(Some(id));
797 id
798 }
799 }
800 }
801
802 pub fn map<M>(self, map: M) -> Self
804 where
805 M: FnOnce(W) -> W,
806 {
807 let EdgeWidget {
808 edge,
809 mut widget,
810 widget_id,
811 } = self;
812 widget = map(widget);
813 EdgeWidget {
814 edge,
815 widget,
816 widget_id,
817 }
818 }
819
820 pub fn set(self, ui: &mut UiCell) -> W::Event {
822 let widget_id = self.widget_id(ui);
823 let EdgeWidget { edge, widget, .. } = self;
824 widget.parent(edge.graph_id).set(widget_id, ui)
825 }
826}
827
828impl<'a, N, E> Graph<'a, N, E>
829where
830 N: Iterator,
831 N::Item: NodeId,
832 E: Iterator<Item = (NodeSocket<N::Item>, NodeSocket<N::Item>)>,
833{
834 pub fn new<NI, EI>(nodes: NI, edges: EI, layout: &'a Layout<NI::Item>) -> Self
836 where
837 NI: IntoIterator<IntoIter = N, Item = N::Item>,
838 EI: IntoIterator<IntoIter = E, Item = (NodeSocket<N::Item>, NodeSocket<N::Item>)>,
839 {
840 Graph {
841 common: widget::CommonBuilder::default(),
842 style: Style::default(),
843 nodes: nodes.into_iter(),
844 edges: edges.into_iter(),
845 layout: layout,
846 }
847 }
848
849 pub fn background_color(mut self, color: Color) -> Self {
851 self.style.background_color = Some(color);
852 self
853 }
854}
855
856impl<'a, N, E> Widget for Graph<'a, N, E>
857where
858 N: Iterator,
859 N::Item: NodeId,
860 E: Iterator<Item = (NodeSocket<N::Item>, NodeSocket<N::Item>)>,
861{
862 type State = State<N::Item>;
863 type Style = Style;
864 type Event = SessionEvents<N::Item>;
865
866 fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
867 let events = VecDeque::new();
868 let nodes = HashMap::new();
869 let node_ids = Vec::new();
870 let edges = Vec::new();
871 let type_widget_ids = HashMap::new();
872 let node_widget_ids = HashMap::new();
873 let widget_id_map = WidgetIdMap {
874 type_widget_ids,
875 node_widget_ids,
876 };
877 let shared = Shared {
878 events,
879 nodes,
880 node_ids,
881 edges,
882 widget_id_map,
883 };
884 State {
885 ids: Ids::new(id_gen),
886 shared: Arc::new(Mutex::new(shared)),
887 }
888 }
889
890 fn style(&self) -> Self::Style {
891 self.style.clone()
892 }
893
894 fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
895 let widget::UpdateArgs {
896 id,
897 state,
898 style,
899 rect,
900 ui,
901 ..
902 } = args;
903 let Graph {
904 nodes,
905 edges,
906 layout,
907 ..
908 } = self;
909 let mut shared = state.shared.lock().unwrap();
910
911 shared.widget_id_map.reset_indices();
913
914 match iter_diff(&shared.node_ids, nodes) {
916 Some(diff) => match diff {
917 IterDiff::FirstMismatch(i, mismatch) => {
918 shared.node_ids.truncate(i);
919 shared.node_ids.extend(mismatch);
920 }
921 IterDiff::Longer(remaining) => {
922 shared.node_ids.extend(remaining);
923 }
924 IterDiff::Shorter(total) => {
925 shared.node_ids.truncate(total);
926 }
927 },
928 None => (),
929 }
930
931 match iter_diff(&shared.edges, edges) {
933 Some(diff) => match diff {
934 IterDiff::FirstMismatch(i, mismatch) => {
935 shared.edges.truncate(i);
936 shared.edges.extend(mismatch);
937 }
938 IterDiff::Longer(remaining) => {
939 shared.edges.extend(remaining);
940 }
941 IterDiff::Shorter(total) => {
942 shared.edges.truncate(total);
943 }
944 },
945 None => (),
946 }
947
948 shared.nodes.clear();
950 for i in 0..shared.node_ids.len() {
951 let node_id = shared.node_ids[i];
953
954 let point = layout.map.get(&node_id).map(|&p| p).unwrap_or([0.0; 2]);
956
957 let point = match shared
959 .widget_id_map
960 .node_widget_ids
961 .get(&node_id)
962 .map(|&w| w)
963 {
964 None => point,
965 Some(widget_id) => {
966 let (dragged_x, dragged_y) = ui
967 .widget_input(widget_id)
968 .drags()
969 .left()
970 .fold((0.0, 0.0), |(x, y), d| {
971 (x + d.delta_xy[0], y + d.delta_xy[1])
972 });
973
974 if dragged_x == 0.0 && dragged_y == 0.0 {
976 point
977 } else {
978 let to = [point[0] + dragged_x, point[1] + dragged_y];
979 let node_event = NodeEvent::Dragged {
980 node_id,
981 from: point,
982 to,
983 };
984 let event = Event::Node(node_event);
985 shared.events.push_back(event);
986 to
987 }
988 }
989 };
990
991 let node = NodeInner { point };
992 shared.nodes.insert(node_id, node);
993 }
994
995 let background_color = style.background_color(&ui.theme);
996 widget::Rectangle::fill(rect.dim())
997 .xy(rect.xy())
998 .color(background_color)
999 .parent(id)
1000 .graphics_for(id)
1001 .set(state.ids.background, ui);
1002
1003 shared.widget_id_map.clear_node_mappings();
1005
1006 let graph_id = id;
1007 let shared = Arc::downgrade(&state.shared);
1008 let session = Session { graph_id, shared };
1009 SessionEvents { session }
1010 }
1011}