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