conrod_core/widget/graph/
mod.rs

1//! A widget for viewing and controlling graph structures.
2
3use 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
17/// Traits required by types that may be used as a graph node identifier.
18///
19/// This trait has a blanket implementation for all types that satisfy the bounds.
20pub 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/// Stores the layout of all nodes within the graph.
24///
25/// All positions are relative to the centre of the `Graph` widget.
26///
27/// Nodes can be moved by
28#[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/// A widget used for visualising and manipulating **Graph** types.
56#[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    /// Data necessary and common for all widget builder types.
64    #[conrod(common_builder)]
65    pub common: widget::CommonBuilder,
66    /// Unique styling for the **Graph**.
67    pub style: Style,
68    /// All nodes within the graph that the widget is to represent.
69    pub nodes: N,
70    /// All edges within the graph.
71    pub edges: E,
72    /// The position of each node within the graph.
73    pub layout: &'a Layout<N::Item>,
74}
75
76/// Unique styling for the **BorderedRectangle** widget.
77#[derive(Copy, Clone, Debug, Default, PartialEq, WidgetStyle_)]
78pub struct Style {
79    /// Shape styling for the inner rectangle.
80    #[conrod(default = "color::TRANSPARENT")]
81    pub background_color: Option<Color>,
82}
83
84widget_ids! {
85    struct Ids {
86        // The rectangle over which all nodes are placed.
87        background,
88    }
89}
90
91/// Unique state for the `Graph`.
92pub struct State<NI>
93where
94    NI: NodeId,
95{
96    ids: Ids,
97    shared: Arc<Mutex<Shared<NI>>>,
98}
99
100// State shared between the **Graph**'s **State** and the returned **Session**.
101struct Shared<NI>
102where
103    NI: NodeId,
104{
105    // A queue of events collected during `set` so that they may be emitted during
106    // **SessionEvents**.
107    events: VecDeque<Event<NI>>,
108    // A mapping from node IDs to their data.
109    nodes: HashMap<NI, NodeInner>,
110    // A list of indices, one for each node in the graph.
111    node_ids: Vec<NI>,
112    // A list of all edges where (a, b) represents the directed edge a -> b.
113    edges: Vec<(NodeSocket<NI>, NodeSocket<NI>)>,
114    // A map from type identifiers to available `widget::Id`s for those types.
115    widget_id_map: WidgetIdMap<NI>,
116}
117
118// A type for managing the input and output socket layouts.
119#[derive(Copy, Clone, Debug)]
120struct SocketLayouts {
121    input: SocketLayout,
122    output: SocketLayout,
123}
124
125// A list of `widget::Id`s for a specific type.
126#[derive(Default)]
127struct TypeWidgetIds {
128    // The index of the next `widget::Id` to use for this type.
129    next_index: usize,
130    // The list of widget IDs.
131    widget_ids: Vec<widget::Id>,
132}
133
134impl TypeWidgetIds {
135    // Return the next `widget::Id` for a widget of the given type.
136    //
137    // If there are no more `Id`s available for the type, a new one will be generated from the
138    // given `widget::id::Generator`.
139    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// A mapping from types to their list of IDs.
153#[derive(Default)]
154struct WidgetIdMap<NI>
155where
156    NI: NodeId,
157{
158    // A map from types to their available `widget::Id`s
159    type_widget_ids: HashMap<TypeId, TypeWidgetIds>,
160    // A map from node IDs to their `widget::Id`.
161    //
162    // This is cleared at the end of each `Widget::update` and filled during the `Node`
163    // instantiation phase.
164    node_widget_ids: HashMap<NI, widget::Id>,
165}
166
167impl<NI> WidgetIdMap<NI>
168where
169    NI: NodeId,
170{
171    // Resets the index for every `TypeWidgetIds` list to `0`.
172    //
173    // This should be called at the beginning of the `Graph` update to ensure each widget
174    // receives a unique ID. If this is not called, the graph will request more and more
175    // `widget::Id`s every update and quickly bloat the `Ui`'s inner widget graph.
176    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    // Clears the `node_id` -> `widget_id` mappings so that they may be recreated during the next
183    // node instantiation stage.
184    fn clear_node_mappings(&mut self) {
185        self.node_widget_ids.clear();
186    }
187
188    // Return the next `widget::Id` for a widget of the given type.
189    //
190    // If there are no more `Id`s available for the type, a new one will be generated from the
191    // given `widget::id::Generator`.
192    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    // Return the next `widget::Id` for a widget of the given type.
211    //
212    // If there are no more `Id`s available for the type, a new one will be generated from the
213    // given `widget::id::Generator`.
214    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/// An interaction has caused some event to occur.
229//
230// TODO:
231//
232// - Hovered near outlet.
233// - Edge end hovered near an outlet?
234#[derive(Clone, Debug, PartialEq)]
235pub enum Event<NI> {
236    /// Events associated with nodes.
237    Node(NodeEvent<NI>),
238    /// Events associated with edges.
239    Edge(EdgeEvent<NI>),
240}
241
242/// Represents a socket connection on a node.
243///
244/// Assumed to be either an input or output socket based on its usage within a tuple. E.g. given
245/// two sockets *(a, b)*, socket *a*'s `socket_index` refers its index within `a`'s ***output***
246/// socket list, while *b*'s refers its index within `b`'s ***input*** socket list.
247#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
248pub struct NodeSocket<NI> {
249    /// The unique identifier for the node.
250    pub id: NI,
251    /// The index of the socket on one side of the node.
252    ///
253    /// E.g. if the socket is the 3rd output socket, index would be `2`.
254    pub socket_index: usize,
255}
256
257/// Events related to adding and removing nodes.
258#[derive(Copy, Clone, Debug, PartialEq)]
259pub enum NodeEvent<NI> {
260    /// The user attempted to remove the node with the given identifier.
261    Remove(NI),
262    /// The widget used to represent this `Node` has been dragged.
263    Dragged {
264        /// Unique identifier of the node being dragged.
265        node_id: NI,
266        /// The origin of the drag relative to the `Graph` widget position.
267        from: Point,
268        /// The end of the drag relative to the `Graph` widget position.
269        to: Point,
270    },
271}
272
273/// Events related to adding and removing edges.
274#[derive(Copy, Clone, Debug, PartialEq, Eq)]
275#[allow(missing_docs)]
276pub enum EdgeEvent<NI> {
277    /// The user has pressed the given node socket with the left mouse button to begin creating an
278    /// edge.
279    AddStart(NodeSocket<NI>),
280    /// The user has attempted to create an edge between the two given node sockets.
281    Add {
282        start: NodeSocket<NI>,
283        end: NodeSocket<NI>,
284    },
285    /// The user has cancelled creating an edge from the given socket.
286    Cancelled(NodeSocket<NI>),
287    /// The user has attempted to remove the edge connecting the two given sockets.
288    Remove {
289        start: NodeSocket<NI>,
290        end: NodeSocket<NI>,
291    },
292}
293
294/// The camera used to view the graph.
295///
296/// The camera supports 2D positioning and zoom.
297#[derive(Copy, Clone, Debug, Default, PartialEq)]
298pub struct Camera {
299    // The position of the camera over the floorplan.
300    //
301    // [0.0, 0.0] - the centre of the graph.
302    point: Point,
303    // The higher the zoom, the closer the floorplan appears.
304    //
305    // The zoom can be multiplied by a distance in metres to get the equivalent distance as a GUI
306    // scalar value.
307    //
308    // 1.0 - Original resolution.
309    // 0.5 - 50% view.
310    zoom: Scalar,
311}
312
313/// A context for moving through the modes of graph widget instantiation in a type-safe manner.
314///
315/// The **Session** is shared between 3 stages:
316///
317/// 1. **SessionEvents**: Emit all graph events that have occurred since the last instantiation.
318/// 2. **SessionNodes**: Instantiate all node widgets in the graph.
319/// 3. **SessionEdges**: Instantiate all edge widgets in the graph.
320///
321/// NOTE: This should allow for different instantiation orders, e.g: nodes then edges, all
322/// connected components in topo order, edges then nodes, etc.
323pub struct Session<NI: NodeId> {
324    // The unique identifier used to instantiate the graph widget.
325    graph_id: widget::Id,
326    // State shared with the `Graph` widget.
327    shared: Weak<Mutex<Shared<NI>>>,
328}
329
330/// The first stage of the graph's **Session** event.
331pub struct SessionEvents<NI: NodeId> {
332    session: Session<NI>,
333}
334
335/// The second stage of the graph's **Session** event.
336pub struct SessionNodes<NI: NodeId> {
337    session: Session<NI>,
338}
339
340/// The third stage of the graph's **Session** event.
341pub struct SessionEdges<NI: NodeId> {
342    session: Session<NI>,
343}
344
345/// An iterator yielding all pending events.
346pub struct Events<'a, NI: NodeId> {
347    shared: Arc<Mutex<Shared<NI>>>,
348    // Bind the lifetime to the `SessionEvents` so the user can't leak the `Shared` state.
349    lifetime: PhantomData<&'a ()>,
350}
351
352/// An iterator-like type yielding a `NodeContext` for every node in the graph.
353///
354/// Each `NodeContext` can be used for instantiating a widget for each node in the graph.
355pub struct Nodes<'a, NI: 'a + NodeId> {
356    // Index into the `node_ids`, indicating which node we're up to.
357    index: usize,
358    shared: Arc<Mutex<Shared<NI>>>,
359    // The `widget::Id` of the parent graph widget.
360    graph_id: widget::Id,
361    // Bind the lifetime to the `SessionNodes` so the user can't leak the `Shared` state.
362    lifetime: PhantomData<&'a NI>,
363}
364
365// Node data stored within the
366#[derive(Copy, Clone)]
367struct NodeInner {
368    point: Point,
369}
370
371/// A context for a node yielded during the node instantiation stage.
372///
373/// This type can be used to:
374///
375/// 1. Get the position of the node via `point()`.
376/// 2. Get the ID for this node via `node_id()`.
377/// 3. Convert into a `NodeWidget` ready for instantiation within the `Ui` via `widget(a_widget)`.
378pub struct NodeContext<'a, NI: 'a + NodeId> {
379    node_id: NI,
380    point: Point,
381    // The `widget::Id` of the `NodeContext`'s parent `Graph` widget.
382    graph_id: widget::Id,
383    shared: Arc<Mutex<Shared<NI>>>,
384    // Bind the lifetime to the `SessionNodes` so the user can't leak the `Shared` state.
385    lifetime: PhantomData<&'a NI>,
386}
387
388/// Returned when a `NodeContext` is assigned a widget.
389///
390/// This intermediary type allows for accessing the `widget::Id` before the widget itself is
391/// instantiated.
392pub struct NodeWidget<'a, NI: 'a + NodeId, W> {
393    node: NodeContext<'a, NI>,
394    widget: W,
395    // `None` if not yet requested the `WidgetIdMap`. `Some` if it has.
396    widget_id: Cell<Option<widget::Id>>,
397}
398
399/// An iterator-like type yielding a `NodeContext` for every node in the graph.
400///
401/// Each `NodeContext` can be used for instantiating a widget for each node in the graph.
402pub struct Edges<'a, NI: 'a + NodeId> {
403    // The index into the `shared.edges` `Vec` that for the next `Edge` that is to be yielded.
404    index: usize,
405    shared: Arc<Mutex<Shared<NI>>>,
406    // The `widget::Id` of the parent graph widget.
407    graph_id: widget::Id,
408    // Bind the lifetime to the `SessionEdges` so the user can't leak the `Shared` state.
409    lifetime: PhantomData<&'a ()>,
410}
411
412/// A context for an edge yielded during the edge instantiation stage.
413///
414/// Tyis type can
415pub struct Edge<'a, NI: NodeId> {
416    // The `widget::Id` of the `Edge`'s parent `Graph` widget.
417    graph_id: widget::Id,
418    // The data shared with the graph state, used to access the `WidgetIdMap`.
419    shared: Arc<Mutex<Shared<NI>>>,
420    // The start of the edge.
421    start: NodeSocket<NI>,
422    // The end of the edge.
423    end: NodeSocket<NI>,
424    // Bind the lifetime to the `SessionEdges` so the user can't leak the `Shared` state.
425    lifetime: PhantomData<&'a ()>,
426}
427
428/// Returned when an `Edge` is assigned a widget.
429///
430/// This intermediary type allows for accessing the `widget::Id` before the widget itself is
431/// instantiated.
432pub struct EdgeWidget<'a, NI: 'a + NodeId, W> {
433    edge: Edge<'a, NI>,
434    widget: W,
435    // `None` if not yet requested the `WidgetIdMap`. `Some` if it has.
436    widget_id: Cell<Option<widget::Id>>,
437}
438
439// impl<NI> Layout<NI>
440// where
441//     NI: Eq + Hash,
442// {
443//     /// The position of the node at the given node identifier.
444//     pub fn get(&self, node_id: NI) -> Option<&Point> {
445//         self.map.get(&node_id)
446//     }
447//     /// The position of the node at the given node identifier.
448//     pub fn get_mut(&mut self, node_id: NI) -> Option<&mut Point> {
449//         self.map.get_mut(&node_id)
450//     }
451// }
452
453impl<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    /// All events that have occurred since the last
477    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    /// Transition from the **SessionEvents** into **SessionNodes** for instantiating nodes.
490    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    /// Produce an iterator yielding a `NodeContext` for each node present in the graph.
514    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    /// Transition from the **SessionNodes** into **SessionEdges** for instantiating edges.
530    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    /// Produce an iterator yielding an `Edge` for each node present in the graph.
568    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    /// The unique identifier associated with this node.
609    pub fn node_id(&self) -> NI {
610        self.node_id
611    }
612
613    /// The location of the node.
614    pub fn point(&self) -> Point {
615        self.point
616    }
617
618    /// Specify the widget to use
619    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    /// Retrieve the `widget::Id` that will be used to instantiate this node's widget.
634    pub fn widget_id(&self, ui: &mut UiCell) -> widget::Id {
635        match self.widget_id.get() {
636            Some(id) => id,
637            None => {
638                // Request a `widget::Id` from the `WidgetIdMap`.
639                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    /// Map over the inner widget.
650    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    /// Set the given widget for the node at `node_id()`.
668    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    /// The start (or "input") for the edge.
693    ///
694    /// This is described via the node's `Id` and the position of its output socket.
695    pub fn start(&self) -> NodeSocket<NI> {
696        self.start
697    }
698
699    /// The end (or "output") for the edge.
700    ///
701    /// This is described via the node's `Id` and the position of its input socket.
702    pub fn end(&self) -> NodeSocket<NI> {
703        self.end
704    }
705
706    /// The start and end sockets.
707    pub fn sockets(&self) -> (NodeSocket<NI>, NodeSocket<NI>) {
708        (self.start, self.end)
709    }
710
711    /// Specify the widget to use
712    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
721/// Returns the `widget::Id` for a node if one exists.
722///
723/// Returns `None` if there is no `Graph` for the given `graph_id` or if there is not yet a
724/// `widget::Id` for the given `node_id`.
725///
726/// This will always return `None` if called between calls to the `Graph::set` and node
727/// instantiation stages, as `widget::Id`s for nodes are only populated during the node
728/// instantiation stage.
729pub 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
746/// Returns the `widget::Id`s for the start and end nodes.
747///
748/// `Edge`s can only exist for the lifetime of a `SessionEdges`, thus we assume that there will
749/// always be a `Graph` for the edge's `graph_id` and that there will always be a `widget::Id`
750/// for the start and end nodes.
751///
752/// **Panic!**s if the given `Ui` is not the same one used to create the edge's parent Graph
753/// widget.
754pub 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    /// Retrieve the `widget::Id` that will be used to instantiate this edge's widget.
787    pub fn widget_id(&self, ui: &mut UiCell) -> widget::Id {
788        match self.widget_id.get() {
789            Some(id) => id,
790            None => {
791                // Request a `widget::Id` from the `WidgetIdMap`.
792                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    /// Apply the given function to the inner widget.
803    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    /// Set the given widget for the edge.
821    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    /// Begin building a new **Graph** widget.
835    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    /// Color the **Graph**'s rectangular area with the given color.
850    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        // Reset the WidgetIdMap indices.
912        shared.widget_id_map.reset_indices();
913
914        // Compare the existing node indices with the new iterator.
915        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        // Compare the existing edges with the new iterator.
932        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        // Use `shared.node_ids` and `shared.edges` to fill `shared.nodes`.
949        shared.nodes.clear();
950        for i in 0..shared.node_ids.len() {
951            // Retrieve the node ID.
952            let node_id = shared.node_ids[i];
953
954            // Get the node position, falling back to 0.0, 0.0 if none was given.
955            let point = layout.map.get(&node_id).map(|&p| p).unwrap_or([0.0; 2]);
956
957            // Check to see if this widget has been dragged since the last update.
958            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 dragging would not move the widget, we're done.
975                    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        // Clear the old node->widget mappings ready for node instantiation.
1004        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}