Пример #1
0
        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)));
        }
Пример #2
0
        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)));
        }
Пример #3
0
        /*
         * 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)));
        }