using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Controls;
using glue.HotValue;
using glue.Extensions.Array;
using glue.Extensions.Enumerable;
namespace glue.WpfUtil
{
public partial class DagLayoutPanel : Panel
{
internal partial class Rail
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
internal abstract class PosBase
{
abstract public RailCalcSet RailCalcs(int iRail = -1);
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
internal class SingleRailPos : PosBase
{
public Rail rail;
protected RailCalcSet rcs;
public SingleRailPos(Rail rail, IHvDouble bv_width, IHvDouble bv_height)
{
this.rail = rail;
this.rcs = new RailCalcSet(rail, this, bv_width, bv_height);
}
public PosBase PosPrevious
{
get
{
int ix = ItemIndex;
return ix == -1 ? null : rail.GetItem(ItemIndex - 1);
}
}
public PosBase PosNext
{
get
{
int ix = ItemIndex;
return ix == -1 ? null : rail.GetItem(ItemIndex + 1);
}
}
public int ItemIndex { get { return rail.FindIndex(this); } }
public void Remove(int ix)
{
if (ix == -1 && (ix = ItemIndex) == -1)
throw new Exception();
Debug.Assert(ix == ItemIndex);
SingleRailPos pAfter = (SingleRailPos)rail.GetItem(ix + 1);
rail.rg.RemoveAt(ix);
this.rail = null;
if (pAfter != null)
pAfter.rcs.RailBase = this.rcs.RailBase;
}
public void Insert(Rail r, int ix)
{
this.rail = r;
this.rcs.RailBase = rail.GetRailStart(ix);
SingleRailPos pAfter = (SingleRailPos)rail.GetItem(ix);
rail.rg.Insert(ix, this);
if (pAfter != null)
pAfter.rcs.RailBase = this.rcs.RightPadded;
}
public void MoveTo(Rail r, ref int new_ix)
{
int old_ix = ItemIndex;
if (old_ix == new_ix)
return;
Remove(old_ix);
if (old_ix < new_ix)
new_ix--;
Insert(r, new_ix);
}
public override RailCalcSet RailCalcs(int iRail = -1)
{
Debug.Assert(iRail == -1 || iRail == rail.RailIndex);
return rcs;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerDisplay("{ToString(),nq}")]
internal class SingleNodePos : SingleRailPos
{
readonly public LayoutDag.Node node;
public SingleNodePos(Rail rail, IHvDouble width, IHvDouble height, int iPos, LayoutDag.Node node)
: base(rail, width, height)
{
this.node = node;
Insert(rail, iPos);
rail.RailSet.RailsLoaded += (o, e) =>
{
SetParentProposal();
SetChildProposal();
node.PropertyChanged += (o1, e1) =>
{
if (e1.PropertyName == "Level")
{
if (node.Level != rail.RailIndex)
{
RailSet rail_set = rail.rs;
Remove(ItemIndex);
rail_set.SetRailCount(node.Dag.MaxLevel + 1);
Rail new_rail = rail_set[node.Level];
Insert(new_rail, new_rail.Count);
}
}
else if (e1.PropertyName == "Child.Item")
{
SetChildProposal();
}
else if (e1.PropertyName == "Parent.Item")
{
SetParentProposal();
}
};
};
}
void SetParentProposal()
{
//Rail.RailCalcSet[] rgrc;
//rgrc = node.PreviousLevelParents.Select(n => n.railpos.RailCalcs(n.Level)).ToArray();
var calcs_by_level = node.Parents
.GroupBy(x => x.Level)
.Select(g => g.Select(y => y.railpos.RailCalcs(g.Key)).ToArray())
.ToArray();
//Debug.WriteLine(this.rcs.MyParentCenter);
if (calcs_by_level.Length == 0)
goto clear_proposal;
if (calcs_by_level.Length == 1)
{
var rgrc = calcs_by_level[0];
if (rgrc.Length == 1)
goto clear_proposal;
this.rcs.MyParentCenter =
new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].Left, rgrc[rgrc.Length - 1].Right);
//new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
// new HvdHalfSpan(rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
}
else
{
var all_calcs = calcs_by_level.SelectMany(g => g).ToArray();
int i_min = all_calcs.IndexOfMin(x => x.Left.Value);
int i_max = all_calcs.IndexOfMax(x => x.Right.Value);
this.rcs.MyParentCenter =
new HvdAddHalfSpan(all_calcs[i_min].SelfBase, all_calcs[i_min].SelfBase, all_calcs[i_max].Right);
//new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
// new HvdHalfSpan(rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
}
return;
clear_proposal:
this.rcs.MyParentCenter = HvdConst.NaN;
}
void SetChildProposal()
{
//Rail.RailCalcSet[] rgrc;
//rgrc = node.PreviousLevelParents.Select(n => n.railpos.RailCalcs(n.Level)).ToArray();
var calcs_by_level = node.Children
.GroupBy(x => x.Level)
.Select(g => g.Select(y => y.railpos.RailCalcs(g.Key)).ToArray())
.ToArray();
//Debug.WriteLine(this.rcs.MyParentCenter);
if (calcs_by_level.Length == 0)
goto clear_proposal;
if (calcs_by_level.Length == 1)
{
var rgrc = calcs_by_level[0];
if (rgrc.Length == 1)
{
this.rcs.MyChildCenter = rgrc[0].Center;
return;
}
this.rcs.MyChildCenter =
new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].Left, rgrc[rgrc.Length - 1].Right);
//new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
// new HvdHalfSpan(rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
}
else
{
var all_calcs = calcs_by_level.SelectMany(g => g).ToArray();
int i_min = all_calcs.IndexOfMin(x => x.Left.Value);
int i_max = all_calcs.IndexOfMax(x => x.Right.Value);
this.rcs.MyChildCenter =
new HvdAddHalfSpan(all_calcs[i_min].SelfBase, all_calcs[i_min].SelfBase, all_calcs[i_max].Right);
//new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
// new HvdHalfSpan(rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
}
return;
//Rail.RailCalcSet[] rgrc;
////rgrc = node.NextLevelChildren.Select(n => n.railpos.RailCalcs(n.Level)).ToArray();
//rgrc = node.AllDescendants.Select(n => n.railpos.RailCalcs(n.Level)).ToArray();
//Debug.WriteLine(this.rcs.MyChildCenter);
//if (rgrc.Length > 1)
//{
// int i_min = rgrc.IndexOfMin(x => x.Left.Value);
// int i_max = rgrc.IndexOfMax(x => x.Right.Value);
// this.rcs.MyChildCenter =
// new HvdAddHalfSpan(rgrc[i_min].SelfBase, rgrc[i_min].Left, rgrc[i_max].Right);
// // new HvdAddHalfSpan(rgrc[0].SelfBase, rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
// // new HvdHalfSpan(rgrc[0].SelfBase, rgrc[rgrc.Length - 1].Right);
//}
clear_proposal:
this.rcs.MyChildCenter = HvdConst.NaN;
}
public override string ToString()
{
return String.Format(@"
{0}
Level: {1}
{2}
",
node.Item.Name,
node.Level,
rcs.ToString());
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class MultiRailPos : PosBase
{
MultiRailPos()
{
}
public override RailCalcSet RailCalcs(int iRail = -1)
{
throw new NotImplementedException();
}
};
};
};
}