Ejemplo n.º 1
0
        private static ImmutableDictionary <CellPos, Cell> CellsReducer(CellsModel parent, ImmutableDictionary <CellPos, Cell> oldCells, object action)
        {
            var newCells = oldCells.MutateEntries(action, (cell, _) => {
                return(ReduceCell(oldCells, cell, action));
            });

            // MyActions.SetCell can also be used to add new cells to the dictionary:
            if (action is MyActions.SetCell s && !newCells.ContainsKey(s.pos))
            {
                newCells = newCells.Add(s.pos, NewCell(s, newCells, isSelected: false));
            }

            // Update all cells that depend on the changed cell:
            int maxDependencySteps = 100;

            for (int i = 0; i < maxDependencySteps; i++)
            {
                if (oldCells == newCells)
                {
                    return(oldCells);
                }
                // As long as there are cells changed because their dependent cells changed repeat updating
                var c = newCells;
                newCells = newCells.MutateEntries(action, (cell, _) => {
                    return(UpdateDependentCell(cell, oldCells, newCells));
                });
                oldCells = c;
            }
            throw new StackOverflowException("Cells have to many transitive dependencies, might be a loop");
        }
Ejemplo n.º 2
0
 public static CellsModel MainReducer(CellsModel previousState, object action)
 {
     using (var mainReducerTiming = Log.MethodEnteredWith(action)) {
         var changed  = false;
         var newCells = previousState.MutateField(previousState.cells, action, CellsReducer, ref changed);
         if (changed)
         {
             return(new CellsModel(newCells));
         }
         return(previousState);
     }
 }
Ejemplo n.º 3
0
        public static void TestDataStoreTransitiveChanges()
        {
            CellsModel model = new CellsModel(ImmutableDictionary <CellPos, Cell> .Empty);
            var        store = new DataStore <CellsModel>(CellsReducers.MainReducer, model, Middlewares.NewLoggingMiddleware <CellsModel>());

            store.Dispatch(new MyActions.SetCell("A", 1, "1 + 1"));
            var  cells = store.SelectElement(s => s.cells);
            Cell a1    = cells()[new CellPos("A", 1)];

            Assert.Equal(2, a1.value);

            // B1 will depend on A1:
            store.Dispatch(new MyActions.SetCell("B", 1, "3 * A1"));
            Cell b1 = cells()[new CellPos("B", 1)];

            Assert.Equal(6, b1.value);

            // C1 will depend on A1 and B1:
            store.Dispatch(new MyActions.SetCell("C", 1, "B1 + 3 - A1"));
            Cell c1 = cells()[new CellPos("C", 1)];

            Assert.Equal(7, c1.value);

            // D1 will depend on C1 (so transitivly also on A1 and B1):
            store.Dispatch(new MyActions.SetCell("D", 1, "2 * C1"));
            Cell d1 = cells()[new CellPos("D", 1)];

            Assert.Equal(14, d1.value);

            // Now changing A1 must have affects to B1, C1, D1 as well:
            store.Dispatch(new MyActions.SetCell("A", 1, "4 + 1"));
            c1 = cells()[new CellPos("C", 1)];
            Assert.Equal(13, c1.value);
            d1 = cells()[new CellPos("D", 1)];
            Assert.Equal(26, d1.value);

            // Select cell C1:
            store.Dispatch(new MyActions.SelectCell(c1.pos));
            Assert.True(cells()[new CellPos("C", 1)].isSelected);
            // Select cell D1:
            store.Dispatch(new MyActions.SelectCell(d1.pos));
            Assert.True(cells()[new CellPos("D", 1)].isSelected);
            Assert.False(cells()[new CellPos("C", 1)].isSelected);

            store.Dispatch(new MyActions.SetCell("A", 3, "1"));
            store.Dispatch(new MyActions.SetCell("A", 2, "A3 + 1"));
            Assert.Throws <MyActions.SetCell.SelfRefException>(() => {
                store.Dispatch(new MyActions.SetCell("A", 3, "A2 + 1"));
            });
        }
Ejemplo n.º 4
0
        public static async Task ShowIn(ViewStack viewStack)
        {
            // Call model unit tests manually before the UI is shown:
            CellsModelTests.TestFromAndToRowName();
            CellsModelTests.TestDataStoreTransitiveChanges();

            CellsModel model = new CellsModel(ImmutableDictionary <CellPos, Cell> .Empty);
            Middleware <CellsModel>      logging   = Middlewares.NewLoggingMiddleware <CellsModel>();
            UndoRedoReducer <CellsModel> undoLogic = new UndoRedoReducer <CellsModel>();
            DataStore <CellsModel>       store     = new DataStore <CellsModel>(undoLogic.Wrap(CellsReducers.MainReducer), model, logging);

            MyPresenter presenter = new MyPresenter();

            presenter.targetView = viewStack.ShowView("7GUIs_Task7_Cells");
            await presenter.LoadModelIntoView(store);

            await TaskV2.Delay(2000);

            Toast.Show("Now simulating some table model changes..");
            // Simulate changes in the model to check if the UI updates correctly:
            CellsModelTests.SimulateSomeChangesInModel(store);
        }
Ejemplo n.º 5
0
        public static async Task TestLoggingOverhead()
        {
            StopwatchV2 t1, t2;

            {
                t1 = Log.MethodEntered("SimulateManyChangesInModel without logging");
                CellsModel model = new CellsModel(ImmutableDictionary <CellPos, Cell> .Empty);
                var        store = new DataStore <CellsModel>(CellsReducers.MainReducer, model);
                await SimulateManyChangesInModel(store);

                Log.MethodDone(t1);
            }
            {
                t2 = Log.MethodEntered("SimulateManyChangesInModel without logging");
                CellsModel model = new CellsModel(ImmutableDictionary <CellPos, Cell> .Empty);
                var        store = new DataStore <CellsModel>(CellsReducers.MainReducer, model, Middlewares.NewLoggingMiddleware <CellsModel>());
                await SimulateManyChangesInModel(store);

                Log.MethodDone(t2);
            }
            // Logging makes mutating the model at least double as slow:
            Assert.True(t1.ElapsedMilliseconds * 2 < t2.ElapsedMilliseconds, $"t1={t1}, t2={t2}");
        }