public static IControl Subdivide(Axis2D axis, IImmutableList <Subdivision> divisions) { if (axis == Axis2D.Vertical && Platform.OperatingSystem == OS.Mac) { divisions = divisions.Reverse().ToImmutableList(); } var u = axis; var v = axis.Opposite(); var sizesV = divisions.Select(d => d.Control.DesiredSize[v]); return(Layer((isRooted, availableSize, parentFrame) => { var frame = ObservableMath.RectangleWithSize(parentFrame.Size); var columns = divisions.Select(d => d.Span).ToArray(); var intervals = frame[axis].Subdivide(columns); var columnCount = columns.Sum(); var tmp = new IControl[intervals.Length]; for (int i = 0; i < intervals.Length; i++) { var span = divisions[i].Span; var ratio = span / columnCount; var node = divisions[i].Control; tmp[i] = node.WithFrame( frame.WithAxis(axis, intervals[i]), availableSize.WithAxis(axis, ov => ov.Mul(ratio))); } return tmp; }) .WithSize(desiredSize: Size.Create( Observable.Return <Points>(0), sizesV.Aggregate(Observable.Return <Points>(0), (a, b) => a.Max(b)), firstAxis: u))); }
public static IControl Stack(Direction2D direction, IObservable <IControl[]> controls) { controls = controls.Replay(1).RefCount(); var edge = (RectangleEdge)direction; edge = edge.FlipVerticallyOnMac(); var u = edge.NormalAxis(); var v = u.Opposite(); return(Layer(self => { return controls .Scan( new { framedControls = (IControl[])null, cache = ImmutableDictionary <IControl, StackItem> .Empty }, (state, currentControls) => { var frame = ObservableMath.RectangleWithSize(self.NativeFrame.Size); var top = frame.GetEdge(edge); var newCache = ImmutableDictionary.CreateBuilder <IControl, StackItem>(); var framedControls = new IControl[currentControls.Length]; for (int i = 0; i < currentControls.Length; i++) { var c = currentControls[i]; StackItem stackItem; if (!state.cache.TryGetValue(c, out stackItem)) { stackItem = new StackItem(c, frame, u); } newCache.Add(c, stackItem); var bottom = edge.IsMinimal() ? top.Add(c.DesiredSize[u]) : top.Sub(c.DesiredSize[u]); bottom = bottom .DistinctUntilChanged() .Replay(1).RefCount(); var res = edge.IsMinimal() ? Interval.FromOffsetLength(top, c.DesiredSize[u]) : Interval.FromOffsetLength(bottom, c.DesiredSize[u]); stackItem.UpdateUAxis(res); top = bottom; framedControls[i] = stackItem.Control; } return new { framedControls, cache = newCache.ToImmutable() }; }) .Select(x => x.framedControls) .Replay(1) .RefCount(); }) .WithSize(desiredSize: Size.Create( controls.Select(s => s.Select(ss => ss.DesiredSize[u])) .ToObservableEnumerable() .Select(l => new Points(l.ConcatOne(0).Sum(p => p.Value))), controls.Select(s => s.Select(ss => ss.DesiredSize[v])) .ToObservableEnumerable() .Select(l => new Points(l.ConcatOne(0).Max(p => p.Value))), firstAxis: u))); }
/* * public IControl Fill(IControl fill = null) * { * var self = _control.Select(c => c.Dock(_edge, fill)).Or(fill); * var root = _parent.Select(p => p.Fill(self)).Or(self); * return root ?? Control.Empty; * } */ public IControl Fill(IControl fill = null) { var stack = new Stack <DockBuilder>(); var db = Optional.Some(this); while (db.HasValue) { stack.Push(db.Value); db = db.Value._parent; } return(Layout.Layer( (isRooted, availableSize, parentFrame) => { var frame = ObservableMath.RectangleWithSize(parentFrame.Size); var controls = new List <IControl>(); while (stack.Count != 0) { var dock = stack.Pop(); if (!dock._control.HasValue) { continue; } var axis = dock._edge.NormalAxis(); var isMinimal = dock._edge.IsMinimal(); var desired = dock._control.Value.DesiredSize[axis]; var total = frame[axis] .DistinctUntilChanged() .Replay(1).RefCount() ; var left = total.Offset .DistinctUntilChanged() .Replay(1).RefCount() ; var right = total.Offset.Add(total.Length) .DistinctUntilChanged() .Replay(1).RefCount() ; var dockedLength = desired.Min(total.Length) .DistinctUntilChanged() .Replay(1).RefCount() ; var dockedOffset = (isMinimal ? left : right.Sub(dockedLength)) .DistinctUntilChanged() .Replay(1).RefCount() ; var filledLength = total.Length.Sub(dockedLength) .DistinctUntilChanged() .Replay(1).RefCount() ; var filledOffset = (isMinimal ? left.Add(dockedLength) : left) .DistinctUntilChanged() .Replay(1).RefCount() ; controls.Add(dock._control.Value .WithFrame( frame: frame.WithAxis(axis, old => Interval.FromOffsetLength(dockedOffset, dockedLength)) .DistinctUntilChanged() .Replay(1).RefCount(), availableSize: availableSize)); frame = frame .WithAxis(axis, old => Interval.FromOffsetLength(filledOffset, filledLength)) .DistinctUntilChanged() .Replay(1).RefCount() ; availableSize = availableSize .WithAxis(axis, old => old.Sub(dockedLength)) .Max(ObservableMath.ZeroSize) .DistinctUntilChanged() .Replay(1).RefCount() ; } if (fill != null) { controls.Add(fill.WithFrame(frame, availableSize)); } return controls; }).WithSize(DesiredSize( fill == null ? ObservableMath.ZeroSize : fill.DesiredSize))); }