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(); } }; }; }