1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

use std::collections::HashMap;
use std::ops::Index;
use super::NodeIndex;
use widget;
use widget::Id as WidgetId;


/// Maps a WidgetId given by the user to a NodeIndex into the Graph (and vice versa).
#[derive(Debug)]
pub struct IndexMap {
    nodes: HashMap<WidgetId, NodeIndex>,
    widgets: HashMap<NodeIndex, WidgetId>,
}


impl IndexMap {

    /// Construct an empty **IndexMap**.
    pub fn new() -> Self {
        IndexMap {
            nodes: HashMap::new(),
            widgets: HashMap::new(),
        }
    }

    /// Construct an **IndexMap** with the given capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        IndexMap {
            nodes: HashMap::with_capacity(capacity),
            widgets: HashMap::with_capacity(capacity),
        }
    }

    /// Add a WidgetId NodeIndex pair.
    pub fn insert(&mut self, widget_id: WidgetId, node_idx: NodeIndex) {
        self.nodes.insert(widget_id, node_idx);
        self.widgets.insert(node_idx, widget_id);
    }

    /// Return Some NodeIndex for the given WidgetId if there is one.
    #[inline]
    pub fn get_node_index(&self, id: WidgetId) -> Option<NodeIndex> {
        self.nodes.get(&id).map(|&idx| idx)
    }

    /// Return Some WidgetId for the given NodeIndex if there is one.
    #[inline]
    pub fn get_widget_id(&self, idx: NodeIndex) -> Option<WidgetId> {
        self.widgets.get(&idx).map(|&id| id)
    }

}

impl Index<WidgetId> for IndexMap {
    type Output = NodeIndex;
    fn index<'a>(&'a self, id: WidgetId) -> &'a NodeIndex {
        self.nodes.get(&id).expect("No NodeIndex for the given WidgetId")
    }
}

impl Index<NodeIndex> for IndexMap {
    type Output = WidgetId;
    fn index<'a>(&'a self, idx: NodeIndex) -> &'a WidgetId {
        self.widgets.get(&idx).expect("No WidgetId for the given NodeIndex")
    }
}


/// A trait for being generic over both WidgetId and NodeIndex.
/// Each method should only return `Some` if they are contained as a key within the given IndexMap.
pub trait GraphIndex: ::std::fmt::Debug + Copy + Clone {
    /// If not one already, convert Self to a WidgetId if it exists within the IndexMap.
    fn to_widget_id(self, map: &IndexMap) -> Option<WidgetId>;
    /// If not one already, convert Self to a NodeIndex if it exists within the IndexMap.
    fn to_node_index(self, map: &IndexMap) -> Option<NodeIndex>;
    /// Convert some GraphIndex type to Self.
    fn from_idx<I: GraphIndex>(other: I, map: &IndexMap) -> Option<Self>;
}


impl GraphIndex for WidgetId {
    fn to_widget_id(self, _map: &IndexMap) -> Option<WidgetId> {
        Some(self)
    }
    fn to_node_index(self, map: &IndexMap) -> Option<NodeIndex> {
        map.get_node_index(self)
    }
    fn from_idx<I: GraphIndex>(other: I, map: &IndexMap) -> Option<Self> {
        other.to_widget_id(map)
    }
}

impl GraphIndex for NodeIndex {
    fn to_widget_id(self, map: &IndexMap) -> Option<WidgetId> {
        map.get_widget_id(self)
    }
    fn to_node_index(self, _map: &IndexMap) -> Option<NodeIndex> {
        Some(self)
    }
    fn from_idx<I: GraphIndex>(other: I, map: &IndexMap) -> Option<Self> {
        other.to_node_index(map)
    }
}

impl GraphIndex for widget::Index {

    /// Coerce a widget::Index into an Option<NodeIndex>.
    /// If the Index is the Internal variant, that idx will be used directly.
    /// If the Index is the Public variant, the index_map will be used to find the matching
    /// NodeIndex.
    fn to_node_index(self, map: &IndexMap) -> Option<NodeIndex> {
        match self {
            widget::Index::Internal(idx) => Some(idx),
            widget::Index::Public(id) => id.to_node_index(map),
        }
    }

    /// Coerce a widget::Index into an Option<WidgetId>.
    /// If the Index is the Public variant, that id will be used directly.
    /// If the Index is the Internal variant, the index_map will be used to find the matching
    /// WidgetId.
    fn to_widget_id(self, map: &IndexMap) -> Option<WidgetId> {
        match self {
            widget::Index::Internal(idx) => idx.to_widget_id(map),
            widget::Index::Public(id) => Some(id),
        }
    }

    /// Construct a widget::Index from some GraphIndex.
    /// First tries to construct a Public variant by checking the IndexMap for a matching WidgetId.
    /// If not WidgetId is found, then tries to find a matching NodeIndex.
    fn from_idx<I: GraphIndex>(other: I, map: &IndexMap) -> Option<Self> {
        other.to_widget_id(map).map(|id| widget::Index::Public(id))
            .or_else(|| other.to_node_index(map).map(|idx| widget::Index::Internal(idx)))
    }

}