private int AddItemToGroup(GroupByKey key, int rowIndex, out bool notify) { notify = false; List <int> rowsInGroup; int groupedIndex; if (_groupedRows.TryGetValue(key, out rowsInGroup)) { groupedIndex = _keyPositions[key]; rowsInGroup.Add(rowIndex); } else { rowsInGroup = new List <int>(); groupedIndex = _groupedRows.AddWithIndex(key, rowsInGroup); _keyPositions.Add(key, groupedIndex); rowsInGroup.Add(rowIndex); foreach (var aggregateColumn in _aggregateColumns) { aggregateColumn.AddField(groupedIndex); } notify = true; // Make sure all the column values are sent too foreach (var keyColumn in _keyColumns) { _updates.OnNext(TableUpdate.NewColumnUpdate(groupedIndex, (IReactiveColumn)keyColumn)); } } return(groupedIndex); }
private bool RemoveItemFromGroup(List <int> @group, int rowIndex, GroupByKey key, int groupedIndex) { group.Remove(rowIndex); var notifyRequired = RemoveEmptyGroup(group, key, groupedIndex); foreach (var aggregateColumn in _aggregateColumns) { aggregateColumn.RemoveOldValue(rowIndex, groupedIndex); } return(notifyRequired); }
private bool RemoveEmptyGroup(List <int> @group, GroupByKey key, int groupedIndex) { if (group.Count == 0) { // Remove the group _groupedRows.RemoveAt(groupedIndex); // _groupedRows.Remove(key); _keyPositions.Remove(key); // Remove the field from the aggregate column foreach (var aggregateColumn in _aggregateColumns) { aggregateColumn.RemoveField(groupedIndex); } return(true); } return(false); }
private void OnSourceValue(TableUpdate tableUpdate) { var columnUpdated = tableUpdate.Column; var sourceIndex = tableUpdate.RowIndex; int groupedIndex; var groupChanged = false; if (tableUpdate.Action == TableUpdateAction.Add) { // New source row added var key = new GroupByKey(_keyColumns, sourceIndex); bool notifyOfAdd; groupedIndex = AddItemToGroup(key, sourceIndex, out notifyOfAdd); if (notifyOfAdd) { NotifyOfGroupAdd(groupedIndex); } _sourceRowsToKeys.Add(sourceIndex, key); groupChanged = true; } else if (tableUpdate.Action == TableUpdateAction.Delete) { // Source row deleted var key = _sourceRowsToKeys[sourceIndex]; var group = _groupedRows[key]; groupedIndex = _keyPositions[key]; if (RemoveItemFromGroup(@group, sourceIndex, key, groupedIndex)) { NotifyOfGroupDelete(groupedIndex); } _sourceRowsToKeys.Remove(sourceIndex); groupChanged = true; } else if (tableUpdate.Action == TableUpdateAction.Update && _groupColumns.ContainsKey(columnUpdated.ColumnId)) { // Source row changing group var key = _sourceRowsToKeys[sourceIndex]; // TODO: figure out how to do this without allocations var newKey = new GroupByKey(_keyColumns, sourceIndex); // Move the rowIndex from the old key to the new key var group = _groupedRows[key]; var oldGroupIndex = _keyPositions[key]; var notifyOfDelete = RemoveItemFromGroup(@group, sourceIndex, key, oldGroupIndex); bool notifyOfAdd; groupedIndex = AddItemToGroup(newKey, sourceIndex, out notifyOfAdd); NotifyOnGroupChange(notifyOfAdd, notifyOfDelete, oldGroupIndex, groupedIndex); // Replace the rowIndex to key mapping _sourceRowsToKeys[sourceIndex] = newKey; var column = FindKeyColumn(columnUpdated.ColumnId, _keyColumns); column.NotifyObserversOnNext(groupedIndex); _updates.OnNext(TableUpdate.NewColumnUpdate(groupedIndex, (IReactiveColumn)column)); // Console.WriteLine("Grouped column updated"); groupChanged = true; } else { var key = _sourceRowsToKeys[sourceIndex]; groupedIndex = _keyPositions[key]; // Console.WriteLine("Non grouped column updated"); } // Aggregated column has changed or group changed which forces re-calc. foreach (var aggregateColumn in _aggregateColumns) { if (groupChanged || tableUpdate.Column.ColumnId == aggregateColumn.SourceColumn.ColumnId) { aggregateColumn.ProcessValue(sourceIndex, groupedIndex); _updates.OnNext(TableUpdate.NewColumnUpdate(groupedIndex, aggregateColumn)); } } }