using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.ComponentModel;
using miew.Enumerable;
using miew.Dag;
namespace agree.Wpf.Util
{
public partial class DagLayoutPanel : Panel
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
internal partial class LayoutDag : Dag<LayoutDag.Node>
{
readonly DagLayoutPanel panel;
readonly Dictionary<FrameworkElement, Node> layouts = new Dictionary<FrameworkElement, Node>();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// constructor
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public LayoutDag(DagLayoutPanel panel)
{
this.panel = panel;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// map the user specified child nodes, which are FrameworkElements of any type, to the internal node
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Node this[FrameworkElement fe]
{
get { return layouts[fe]; }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool Contains(FrameworkElement fe)
{
return layouts.ContainsKey(fe);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool AddChild(FrameworkElement fe)
{
if (fe.Visibility != Visibility.Visible)
return false;
Node node;
if (!layouts.TryGetValue(fe, out node))
{
layouts.Add(fe, node = new Node(this, fe));
node.PropertyChanged += level_repeater;
}
foreach (FrameworkElement fe_par in VisibleDagParents(fe))
{
Node n_par = layouts[fe_par];
node.AddParent(n_par);
}
/// Attach a hook on node visibility.
fe.IsVisibleChanged += visibility_hook;
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void RemoveChild(FrameworkElement fe)
{
Node n;
if (!layouts.TryGetValue(fe, out n))
throw new Exception();
fe.IsVisibleChanged -= visibility_hook;
base.Remove(n);
n.PropertyChanged -= level_repeater;
layouts.Remove(fe);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// static hook functions conserve closures
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static PropertyChangedEventHandler level_repeater = (sender, e) =>
{
if (e.PropertyName == "Level")
{
Node n = sender as Node;
n.Item.SetValue(DagLevelPropertyKey, n.Level);
}
};
static DependencyPropertyChangedEventHandler visibility_hook = (sender, args) =>
{
FrameworkElement fe = sender as FrameworkElement;
if (fe != null)
{
DagLayoutPanel dlp = fe.Parent as DagLayoutPanel;
dlp._dag.ItemVisibilityChanged(fe);
}
};
void ItemVisibilityChanged(FrameworkElement fe)
{
if (fe.Visibility == Visibility.Hidden)
this.RemoveChild(fe);
else
this.AddChild(fe);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool ChangeNodeParents(FrameworkElement fe, IEnumerable<FrameworkElement> iefe)
{
Node n;
if (!layouts.TryGetValue(fe, out n))
throw new Exception();
return n.ChangeParents(iefe.Select(fe_par => layouts[fe_par]));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool ReMeasureChild(FrameworkElement fe)
{
Node n;
if (!layouts.TryGetValue(fe, out n))
throw new Exception();
return n.ReMeasure();
}
};
};
}