Ejemplo n.º 1
0
            public IDisposable ListenUpdates(Action <T2> reaction)
            {
                var group = new CellJoinDisposable <T2>();

                group.lastValue = value;

                Action <T> func = iVal =>
                {
                    if (group.disposed)
                    {
                        return;
                    }
                    var innerCell = map(iVal);
                    if (@group.Second != null)
                    {
                        var innerVal = innerCell.value;
                        if (!EqualityComparer <T2> .Default.Equals(group.lastValue, innerVal))
                        {
                            reaction(innerVal);
                            group.lastValue = innerVal;
                        }
                        @group.Second.Dispose();
                    }

                    @group.Second = innerCell.ListenUpdates(val =>
                    {
                        reaction(val);
                        group.lastValue = val;
                    });
                };

                @group.First = cell.Bind(func);
                return(group);
            }
Ejemplo n.º 2
0
    public static ICell <T3> Merge <T, T2, T3>(this ICell <T> cell, ICell <T2> cell2, Func <T, T2, T3> func)
    {
        Func <T3> curr = () => func(cell.value, cell2.value);

        return(new AnonymousCell <T3>((Action <T3> reaction, Priority p) =>
        {
            var disp = new CellJoinDisposable <T3>();
            disp.lastValue = func(cell.value, cell2.value);
            disp.Add(cell.ListenUpdates(val =>
            {
                T3 newCurr = curr();
                if (!object.Equals(newCurr, disp.lastValue))
                {
                    disp.lastValue = newCurr;
                    reaction(newCurr);
                }
            }, p));
            disp.Add(cell2.ListenUpdates(val =>
            {
                T3 newCurr = curr();
                if (!object.Equals(newCurr, disp.lastValue))
                {
                    disp.lastValue = newCurr;
                    reaction(newCurr);
                }
            }, p));
            return disp;
        }, curr));
    }
Ejemplo n.º 3
0
    /*  Pass plain formula and recieve fully subscribed reactive cell
     *
     *  Example:
     *  var relativeHp = Calculate(() = > {
     *      if (monster.value == null) return 0;
     *      return monster.value.hp.value / monster.maxHealth.value;
     *  });
     *
     *  Restrictions:
     *  1 Do not do bind, listen, connections dispose or other operations. Write pure calculation code.
     *  2 Do not change state. Your formula should not mutate world. Only constant access.
     *  3 Do not use reactive values in code branches or it will not be subscribed properly. (May be fixed later)
     */
    public static ICell <T> Calculate <T>(Func <T> formula)
    {
        calculationMode = true;
        var probe = formula();

        calculationMode = false;

        var copyTouched = touched;

        touched = new List <ICell>();

        return(new AnonymousCell <T>((Action <T> reaction, Priority p) => {
            CellJoinDisposable <T> group = new CellJoinDisposable <T>();
            group.SetArray(copyTouched.Select(cell => cell.OnChanged(() =>
            {
                var val = formula();
                if (!object.Equals(group.lastValue, val))
                {
                    reaction(val);
                    group.lastValue = val;
                }
            }, p)));
            group.lastValue = formula();
            return group;
        }, () => formula()));
    }
Ejemplo n.º 4
0
    public static ICell <IEnumerable <T> > ToCellOfCollection <T>(this IEnumerable <ICell <T> > cells)
    {
        Func <IEnumerable <T> > values = () => cells.Select(cell => cell.value);

        return(new AnonymousCell <IEnumerable <T> >((Action <IEnumerable <T> > reaction, Priority p) =>
        {
            CellJoinDisposable <T> group = new CellJoinDisposable <T> {
            };
            foreach (var cell in cells)
            {
                group.Add(cell.ListenUpdates(_ => reaction(values()), p));
            }
            return group;
        }, values));
    }
Ejemplo n.º 5
0
            public IDisposable ListenUpdates(Action <T> reaction)
            {
                ICell <T> currInnerCell = cell.value;

                CheckInnerCell(currInnerCell);

                var group = new CellJoinDisposable <T>();

                Action <ICell <T> > func = innerCell =>
                {
                    if (group.disposed)
                    {
                        return;
                    }

                    CheckInnerCell(innerCell);

                    if (group.Second != null)
                    {
                        var innerVal = innerCell.value;
                        if (!EqualityComparer <T> .Default.Equals(group.lastValue, innerVal))
                        {
                            reaction(innerVal);
                            group.lastValue = innerVal;
                        }
                        group.Second.Dispose();
                    }

                    group.Second = innerCell.ListenUpdates(val =>
                    {
                        reaction(val);
                        group.lastValue = val;
                    });
                };

                group.lastValue = currInnerCell.value;
                func(cell.value);
                group.First = cell.ListenUpdates(func);
                return(group);
            }
Ejemplo n.º 6
0
    static public IStream <T> Join <T>(this ICell <IStream <T> > cell)
    {
        return(new AnonymousStream <T>((Action <T> reaction, Priority p) =>
        {
            SingleAssignmentDisposable mainDisposable = new SingleAssignmentDisposable();
            SingleAssignmentDisposable inner = new SingleAssignmentDisposable();
            CellJoinDisposable <T> group = new CellJoinDisposable <T> {
                mainDisposable, inner
            };

            Action <IStream <T> > func = (IStream <T> innerStream) =>
            {
                inner.Dispose();
                if (innerStream != null)
                {
                    inner.Disposable = innerStream.Listen(reaction, p);
                }
            };

            mainDisposable.Disposable = cell.Bind(func, p);
            return group;
        }));
    }
Ejemplo n.º 7
0
    public static ICell <T> Join <T>(this ICell <ICell <T> > cell)
    {
        return(new AnonymousCell <T>((Action <T> reaction, Priority p) =>
        {
            SingleAssignmentDisposable mainDisposable = new SingleAssignmentDisposable();
            SingleAssignmentDisposable inner = new SingleAssignmentDisposable();
            CellJoinDisposable <T> group = new CellJoinDisposable <T> {
                mainDisposable, inner
            };
            group.lastValue = cell.value.value;

            Action <ICell <T> > func = (ICell <T> innerCell) =>
            {
                if (!inner.IsDisposed)
                {
                    T value = innerCell.value;
                    if (!object.Equals(group.lastValue, value))
                    {
                        reaction(value);
                        group.lastValue = value;
                    }
                    inner.Dispose();
                }

                inner.Disposable = innerCell.ListenUpdates(val =>
                {
                    reaction(val);
                    group.lastValue = val;
                }, p);
            };

            func(cell.value);

            mainDisposable.Disposable = cell.ListenUpdates(func, p);
            return group;
        }, () => cell.value.value));
    }