use daggy;
use position::{Axis, Depth, Point, Rect};
use std;
use std::any::Any;
use std::ops::{Index, IndexMut};
use widget::{self, Widget};
pub use self::depth_order::DepthOrder;
pub use daggy::Walker;
pub mod algo;
pub mod depth_order;
pub type EdgeIndex = daggy::EdgeIndex<u32>;
pub type IndexPair = (EdgeIndex, widget::Id);
pub type Parents = daggy::Parents<Node, Edge, u32>;
pub type Children = daggy::Children<Node, Edge, u32>;
pub type PositionParents =
std::iter::Chain<std::option::IntoIter<widget::Id>, std::option::IntoIter<widget::Id>>;
pub type FilteredChildren =
daggy::walker::Filter<Children, fn(&Graph, EdgeIndex, widget::Id) -> bool>;
pub type DepthChildren = FilteredChildren;
pub type XPositionChildren = FilteredChildren;
pub type YPositionChildren = FilteredChildren;
pub type PositionChildren = daggy::walker::Chain<Graph, u32, XPositionChildren, YPositionChildren>;
pub type GraphicChildren = FilteredChildren;
pub type RecursiveWalk<F> = daggy::walker::Recursive<Graph, u32, F>;
pub type WouldCycle = daggy::WouldCycle<Edge>;
#[derive(Debug)]
pub struct UniqueWidgetState<State, Style>
where
State: Any,
Style: Any,
{
pub state: State,
pub style: Style,
}
#[derive(Debug)]
pub struct Container {
pub maybe_state: Option<Box<dyn Any + Send>>,
pub type_id: std::any::TypeId,
pub rect: Rect,
pub depth: Depth,
pub kid_area: widget::KidArea,
pub maybe_dragged_from: Option<Point>,
pub maybe_floating: Option<widget::Floating>,
pub crop_kids: bool,
pub maybe_x_scroll_state: Option<widget::scroll::StateX>,
pub maybe_y_scroll_state: Option<widget::scroll::StateY>,
pub instantiation_order_idx: usize,
pub is_over: IsOverFn,
}
#[derive(Copy, Clone)]
pub struct IsOverFn(pub widget::IsOverFn);
impl std::fmt::Debug for IsOverFn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "IsOverFn")
}
}
#[derive(Debug)]
pub enum Node {
Widget(Container),
Placeholder,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Edge {
Position(Axis),
Depth,
Graphic,
}
pub const NUM_EDGE_VARIANTS: usize = 4;
type Dag = daggy::Dag<Node, Edge>;
#[derive(Debug)]
pub struct Graph {
dag: Dag,
}
impl Container {
pub fn state_and_style<State, Style>(&self) -> Option<&UniqueWidgetState<State, Style>>
where
State: Any + 'static,
Style: Any + 'static,
{
self.maybe_state
.as_ref()
.and_then(|boxed_state| boxed_state.downcast_ref())
}
pub fn unique_widget_state<W>(&self) -> Option<&UniqueWidgetState<W::State, W::Style>>
where
W: Widget,
W::State: Any + 'static,
W::Style: Any + 'static,
{
self.state_and_style::<W::State, W::Style>()
}
}
impl Node {
pub fn is_widget(&self) -> bool {
if let Node::Widget(_) = *self {
true
} else {
false
}
}
}
impl Graph {
pub fn new() -> Self {
Graph { dag: Dag::new() }
}
pub fn with_node_capacity(n_nodes: usize) -> Self {
let n_edges = n_nodes * NUM_EDGE_VARIANTS;
Graph {
dag: Dag::with_capacity(n_nodes, n_edges),
}
}
pub fn clear(&mut self) {
self.dag.clear()
}
pub fn node_count(&self) -> usize {
self.dag.node_count()
}
pub fn widget_count(&self) -> usize {
(0..self.node_count())
.filter(|&i| self[widget::Id::new(i)].is_widget())
.count()
}
pub fn edge_count(&self) -> usize {
self.dag.edge_count()
}
pub fn node_capacity(&self) -> usize {
unimplemented!();
}
fn add_node(&mut self, node: Node) -> widget::Id {
self.dag.add_node(node)
}
fn set_edge(
&mut self,
a: widget::Id,
b: widget::Id,
edge: Edge,
) -> Result<EdgeIndex, WouldCycle> {
let mut parents = self.parents(b);
let mut already_set = None;
while let Some((in_edge_idx, in_node_idx)) = parents.next(self) {
if edge == self[in_edge_idx] {
if in_node_idx == a {
already_set = Some(in_edge_idx);
} else {
self.remove_edge(in_edge_idx);
}
break;
}
}
match already_set {
Some(edge_idx) => Ok(edge_idx),
None => self.dag.add_edge(a, b, edge),
}
}
fn remove_edge(&mut self, idx: EdgeIndex) -> Option<Edge> {
self.dag.remove_edge(idx)
}
fn remove_parent_edge(&mut self, id: widget::Id, edge: Edge) -> bool {
if let Some((edge_idx, _)) = self.parents(id).find(self, |g, e, _| g[e] == edge) {
self.remove_edge(edge_idx);
return true;
}
false
}
pub fn add_placeholder(&mut self) -> widget::Id {
self.add_node(Node::Placeholder)
}
pub fn node(&self, idx: widget::Id) -> Option<&Node> {
self.dag.node_weight(idx)
}
pub fn node_mut(&mut self, idx: widget::Id) -> Option<&mut Node> {
self.dag.node_weight_mut(idx)
}
pub fn edge(&self, idx: EdgeIndex) -> Option<&Edge> {
self.dag.edge_weight(idx)
}
pub fn edge_mut(&mut self, idx: EdgeIndex) -> Option<&mut Edge> {
self.dag.edge_weight_mut(idx)
}
pub fn edge_endpoints(&self, idx: EdgeIndex) -> Option<(widget::Id, widget::Id)> {
self.dag.edge_endpoints(idx)
}
pub fn widget(&self, idx: widget::Id) -> Option<&Container> {
self.node(idx).and_then(|node| match *node {
Node::Widget(ref container) => Some(container),
_ => None,
})
}
pub fn widget_mut(&mut self, idx: widget::Id) -> Option<&mut Container> {
self.node_mut(idx).and_then(|node| match *node {
Node::Widget(ref mut container) => Some(container),
_ => None,
})
}
pub fn parents(&self, child: widget::Id) -> Parents {
self.dag.parents(child)
}
pub fn recursive_walk<F>(&self, start: widget::Id, recursive_fn: F) -> RecursiveWalk<F>
where
F: FnMut(&Self, widget::Id) -> Option<(EdgeIndex, widget::Id)>,
{
RecursiveWalk::new(start, recursive_fn)
}
pub fn edge_parent(&self, idx: widget::Id, edge: Edge) -> Option<widget::Id> {
self.parents(idx)
.find(self, |g, e, _| g[e] == edge)
.map(|(_, n)| n)
}
pub fn depth_parent(&self, idx: widget::Id) -> Option<widget::Id> {
self.edge_parent(idx, Edge::Depth)
}
pub fn x_position_parent(&self, idx: widget::Id) -> Option<widget::Id> {
self.edge_parent(idx, Edge::Position(Axis::X))
}
pub fn y_position_parent(&self, idx: widget::Id) -> Option<widget::Id> {
self.edge_parent(idx, Edge::Position(Axis::Y))
}
pub fn position_parents(&self, idx: widget::Id) -> PositionParents {
self.x_position_parent(idx)
.into_iter()
.chain(self.y_position_parent(idx))
}
pub fn graphic_parent(&self, idx: widget::Id) -> Option<widget::Id> {
self.edge_parent(idx, Edge::Graphic)
}
pub fn depth_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn depth_edge_parent(graph: &Graph, idx: widget::Id) -> Option<IndexPair> {
graph
.parents(idx)
.find(graph, |g, e, _| g[e] == Edge::Depth)
}
self.recursive_walk(idx, depth_edge_parent)
}
pub fn x_position_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn x_position_edge_parent(graph: &Graph, idx: widget::Id) -> Option<IndexPair> {
graph
.parents(idx)
.find(graph, |g, e, _| g[e] == Edge::Position(Axis::X))
}
self.recursive_walk(idx, x_position_edge_parent)
}
pub fn y_position_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn y_position_edge_parent(graph: &Graph, idx: widget::Id) -> Option<IndexPair> {
graph
.parents(idx)
.find(graph, |g, e, _| g[e] == Edge::Position(Axis::Y))
}
self.recursive_walk(idx, y_position_edge_parent)
}
pub fn graphic_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn graphic_edge_parent(graph: &Graph, idx: widget::Id) -> Option<IndexPair> {
graph
.parents(idx)
.find(graph, |g, e, _| g[e] == Edge::Graphic)
}
self.recursive_walk(idx, graphic_edge_parent)
}
pub fn scrollable_y_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn scrollable_y_parent(graph: &Graph, id: widget::Id) -> Option<IndexPair> {
let mut depth_parents = graph.depth_parent_recursion(id);
while let Some((e, n)) = depth_parents.next(graph) {
if let Some(parent) = graph.widget(n) {
if parent.maybe_y_scroll_state.is_some() {
return Some((e, n));
}
}
}
None
}
self.recursive_walk(idx, scrollable_y_parent)
}
pub fn scrollable_x_parent_recursion(
&self,
idx: widget::Id,
) -> RecursiveWalk<fn(&Graph, widget::Id) -> Option<IndexPair>> {
fn scrollable_x_parent(graph: &Graph, id: widget::Id) -> Option<IndexPair> {
let mut depth_parents = graph.depth_parent_recursion(id);
while let Some((e, n)) = depth_parents.next(graph) {
if let Some(parent) = graph.widget(n) {
if parent.maybe_x_scroll_state.is_some() {
return Some((e, n));
}
}
}
None
}
self.recursive_walk(idx, scrollable_x_parent)
}
pub fn children(&self, parent: widget::Id) -> Children {
self.dag.children(parent)
}
pub fn depth_children(&self, idx: widget::Id) -> DepthChildren {
self.children(idx).filter(is_depth_edge)
}
pub fn x_position_children(&self, idx: widget::Id) -> XPositionChildren {
self.children(idx).filter(is_x_position_edge)
}
pub fn y_position_children(&self, idx: widget::Id) -> YPositionChildren {
self.children(idx).filter(is_y_position_edge)
}
pub fn position_children(&self, idx: widget::Id) -> PositionChildren {
self.x_position_children(idx)
.chain(self.y_position_children(idx))
}
pub fn graphic_children(&self, idx: widget::Id) -> GraphicChildren {
self.children(idx).filter(is_graphic_edge)
}
pub fn does_edge_exist<F>(&self, parent: widget::Id, child: widget::Id, is_edge: F) -> bool
where
F: Fn(Edge) -> bool,
{
self.parents(child)
.any(self, |g, e, n| n == parent && is_edge(g[e]))
}
pub fn does_depth_edge_exist(&self, parent: widget::Id, child: widget::Id) -> bool {
self.does_edge_exist(parent, child, |e| e == Edge::Depth)
}
pub fn does_position_edge_exist(&self, parent: widget::Id, child: widget::Id) -> bool {
let is_edge = |e| e == Edge::Position(Axis::X) || e == Edge::Position(Axis::Y);
self.does_edge_exist(parent, child, is_edge)
}
pub fn does_graphic_edge_exist(&self, parent: widget::Id, child: widget::Id) -> bool {
self.does_edge_exist(parent, child, |e| e == Edge::Graphic)
}
pub fn does_recursive_edge_exist<F>(
&self,
parent: widget::Id,
child: widget::Id,
is_edge: F,
) -> bool
where
F: Fn(Edge) -> bool,
{
self.recursive_walk(child, |g, n| g.parents(n).find(g, |g, e, _| is_edge(g[e])))
.any(self, |_, _, n| n == parent)
}
pub fn does_recursive_depth_edge_exist(&self, parent: widget::Id, child: widget::Id) -> bool {
self.does_recursive_edge_exist(parent, child, |e| e == Edge::Depth)
}
pub fn does_recursive_graphic_edge_exist(&self, parent: widget::Id, child: widget::Id) -> bool {
self.does_recursive_edge_exist(parent, child, |e| e == Edge::Graphic)
}
pub fn pre_update_cache(
&mut self,
root: widget::Id,
widget: widget::PreUpdateCache,
instantiation_order_idx: usize,
) {
let widget::PreUpdateCache {
type_id,
id,
maybe_parent_id,
maybe_x_positioned_relatively_id,
maybe_y_positioned_relatively_id,
rect,
depth,
kid_area,
maybe_dragged_from,
maybe_floating,
crop_kids,
maybe_x_scroll_state,
maybe_y_scroll_state,
maybe_graphics_for,
is_over,
} = widget;
assert!(
self.node(id).is_some(),
"No node found for the given widget::Id {:?}",
id
);
let new_container = || Container {
maybe_state: None,
type_id: type_id,
rect: rect,
depth: depth,
kid_area: kid_area,
maybe_dragged_from: maybe_dragged_from,
maybe_floating: maybe_floating,
crop_kids: crop_kids,
maybe_x_scroll_state: maybe_x_scroll_state,
maybe_y_scroll_state: maybe_y_scroll_state,
instantiation_order_idx: instantiation_order_idx,
is_over: IsOverFn(is_over),
};
let maybe_parent_id = |graph: &mut Self| match maybe_parent_id {
Some(parent_id) => match graph.node(parent_id).is_some() {
true => Some(parent_id),
false => panic!(
"No node found for the given parent widget::Id {:?}",
parent_id
),
},
None => {
if id == root {
None
} else {
Some(root)
}
}
};
if let Some(parent_id) = maybe_parent_id(self) {
self.set_edge(parent_id, id, Edge::Depth).unwrap();
}
match &mut self.dag[id] {
node @ &mut Node::Placeholder => *node = Node::Widget(new_container()),
&mut Node::Widget(ref mut container) => {
assert!(
container.type_id == type_id,
"A widget of a different type already exists at the given id \
({:?}). You tried to insert a widget with state of type {:?}, \
however the existing widget state is of type {:?}. Check your \
`WidgetId`s for errors.",
id,
&type_id,
container.type_id
);
container.type_id = type_id;
container.rect = rect;
container.depth = depth;
container.kid_area = kid_area;
container.maybe_dragged_from = maybe_dragged_from;
container.maybe_floating = maybe_floating;
container.crop_kids = crop_kids;
container.maybe_x_scroll_state = maybe_x_scroll_state;
container.maybe_y_scroll_state = maybe_y_scroll_state;
container.instantiation_order_idx = instantiation_order_idx;
container.is_over = IsOverFn(is_over);
}
}
if let Some(relative_id) = maybe_x_positioned_relatively_id {
self.set_edge(relative_id, id, Edge::Position(Axis::X))
.unwrap();
} else {
self.remove_parent_edge(id, Edge::Position(Axis::X));
}
if let Some(relative_id) = maybe_y_positioned_relatively_id {
self.set_edge(relative_id, id, Edge::Position(Axis::Y))
.unwrap();
} else {
self.remove_parent_edge(id, Edge::Position(Axis::Y));
}
if let Some(graphic_parent_id) = maybe_graphics_for {
self.set_edge(graphic_parent_id, id, Edge::Graphic).unwrap();
} else {
self.remove_parent_edge(id, Edge::Graphic);
}
}
pub fn post_update_cache<W>(&mut self, widget: widget::PostUpdateCache<W>)
where
W: Widget,
W::State: 'static,
W::Style: 'static,
{
let widget::PostUpdateCache {
id, state, style, ..
} = widget;
if let Some(ref mut container) = self.widget_mut(id) {
let unique_state: UniqueWidgetState<W::State, W::Style> = UniqueWidgetState {
state: state,
style: style,
};
container.maybe_state = Some(Box::new(unique_state));
}
}
}
fn is_depth_edge(g: &Graph, e: EdgeIndex, _: widget::Id) -> bool {
g[e] == Edge::Depth
}
fn is_x_position_edge(g: &Graph, e: EdgeIndex, _: widget::Id) -> bool {
g[e] == Edge::Position(Axis::X)
}
fn is_y_position_edge(g: &Graph, e: EdgeIndex, _: widget::Id) -> bool {
g[e] == Edge::Position(Axis::Y)
}
fn is_graphic_edge(g: &Graph, e: EdgeIndex, _: widget::Id) -> bool {
g[e] == Edge::Graphic
}
impl Walker<Graph> for Children {
type Index = u32;
#[inline]
fn next(&mut self, graph: &Graph) -> Option<(EdgeIndex, widget::Id)> {
self.next(&graph.dag)
}
}
impl Walker<Graph> for Parents {
type Index = u32;
#[inline]
fn next(&mut self, graph: &Graph) -> Option<(EdgeIndex, widget::Id)> {
self.next(&graph.dag)
}
}
impl ::std::ops::Index<widget::Id> for Graph {
type Output = Node;
fn index<'a>(&'a self, id: widget::Id) -> &'a Node {
self.node(id).unwrap()
}
}
impl ::std::ops::IndexMut<widget::Id> for Graph {
fn index_mut<'a>(&'a mut self, id: widget::Id) -> &'a mut Node {
self.node_mut(id).unwrap()
}
}
impl Index<EdgeIndex> for Graph {
type Output = Edge;
fn index<'a>(&'a self, idx: EdgeIndex) -> &'a Edge {
self.edge(idx).unwrap()
}
}
impl IndexMut<EdgeIndex> for Graph {
fn index_mut<'a>(&'a mut self, idx: EdgeIndex) -> &'a mut Edge {
self.edge_mut(idx).unwrap()
}
}