use std::collections::HashMap;
use std::ops::Index;
use super::NodeIndex;
use widget;
use widget::Id as WidgetId;
#[derive(Debug)]
pub struct IndexMap {
nodes: HashMap<WidgetId, NodeIndex>,
widgets: HashMap<NodeIndex, WidgetId>,
}
impl IndexMap {
pub fn new() -> Self {
IndexMap {
nodes: HashMap::new(),
widgets: HashMap::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
IndexMap {
nodes: HashMap::with_capacity(capacity),
widgets: HashMap::with_capacity(capacity),
}
}
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);
}
#[inline]
pub fn get_node_index(&self, id: WidgetId) -> Option<NodeIndex> {
self.nodes.get(&id).map(|&idx| idx)
}
#[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")
}
}
pub trait GraphIndex: ::std::fmt::Debug + Copy + Clone {
fn to_widget_id(self, map: &IndexMap) -> Option<WidgetId>;
fn to_node_index(self, map: &IndexMap) -> Option<NodeIndex>;
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 {
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),
}
}
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),
}
}
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)))
}
}