using System;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Shapes;
using glue.Extensions.Enumerable;
using glue.XDag;
namespace glue.WpfUtil
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public partial class DagLayoutPanel : Panel
{
//public enum LayoutDirection
//{
// TopToBottom = 0,
// BottomToTop = 1,
// LeftToRight = 2,
// RightToLeft = 3,
//}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Shape.Stroke - dependency property is adopted by the DagPanel
/// Shape.StrokeThickness - dependency property is adopted by the DagPanel
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static DagLayoutPanel()
{
Shape.StrokeProperty.AddOwner(typeof(DagLayoutPanel),
new FrameworkPropertyMetadata(
Brushes.Black,
0,
(e, o) =>
{
DagLayoutPanel p = (DagLayoutPanel)e;
p.InvalidateVisual();
},
null,
false));
Shape.StrokeThicknessProperty.AddOwner(typeof(DagLayoutPanel),
new FrameworkPropertyMetadata(
1.0,
0,
(e, o) =>
{
DagLayoutPanel p = (DagLayoutPanel)e;
p.InvalidateVisual();
},
null,
false));
}
public Brush Stroke
{
get { return (Brush)GetValue(Shape.StrokeProperty); }
set { SetValue(Shape.StrokeProperty, value); }
}
public Double StrokeThickness
{
get { return (Double)GetValue(Shape.StrokeThicknessProperty); }
set { SetValue(Shape.StrokeThicknessProperty, value); }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// DagParents attached property - establish the Dag topology by setting an IList of parents (or none) for each
/// Dag node (a FrameworkElement)
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static FrameworkElement[] rg_fe_empty = new FrameworkElement[0];
public static readonly DependencyProperty DagParentsProperty =
DependencyProperty.RegisterAttached("DagParents", typeof(IList), typeof(DagLayoutPanel),
new FrameworkPropertyMetadata(
default(IList),
FrameworkPropertyMetadataOptions.AffectsParentMeasure |
FrameworkPropertyMetadataOptions.AffectsParentArrange,
(d, args) =>
{
FrameworkElement fe = d as FrameworkElement;
if (fe != null)
{
DagLayoutPanel dlp = fe.Parent as DagLayoutPanel;
IList new_list = args.NewValue as IList;
IList old_list = args.NewValue as IList;
if (dlp != null && new_list != null)
dlp.ChangeNodeParents(fe, old_list, new_list);
}
},
(d, o) =>
{
IList rg = o as IList;
FrameworkElement fe = d as FrameworkElement;
if (fe == null || rg == null)
return rg_fe_empty;
DagLayoutPanel dlp = fe.Parent as DagLayoutPanel;
if (dlp == null)
return rg_fe_empty;
/// prevent cycles in the dag.
LayoutDag.Node cur_node = dlp._dag[fe];
return rg
.OfType<FrameworkElement>()
.Where(par => par != fe && !cur_node.AllDescendants.Contains(dlp._dag[par]))
.ToArray();
},
true));
public static IList GetDagParents(FrameworkElement e)
{
return e.GetValue(DagParentsProperty) as IList ?? rg_fe_empty;
}
public static void SetDagParents(FrameworkElement e, IList par)
{
e.SetValue(DagParentsProperty, par);
}
static IEnumerable<FrameworkElement> VisibleDagParents(FrameworkElement fe)
{
HashSet<FrameworkElement> hs = new HashSet<FrameworkElement>();
GetVisibleDagParents(hs, fe);
return hs;
}
static void GetVisibleDagParents(HashSet<FrameworkElement> found, FrameworkElement fe)
{
IList parents = fe.GetValue(DagParentsProperty) as IList;
if (parents == null)
return;
foreach (FrameworkElement parent in parents.OfType<FrameworkElement>())
{
if (parent.Visibility == Visibility.Hidden)
GetVisibleDagParents(found, parent);
else
found.Add(parent);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// DagLevel - read-only, attached dependency property indicates the computed level of the node
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static readonly DependencyPropertyKey DagLevelPropertyKey =
DependencyProperty.RegisterAttachedReadOnly(
"DagLevel",
typeof(int),
typeof(DagLayoutPanel),
new FrameworkPropertyMetadata(0));
public static readonly DependencyProperty DagLevelProperty = DagLevelPropertyKey.DependencyProperty;
};
}