private void ValidateRowVisualComplex( RowVisual rowVisual, IntPtr pfstablerow, int tableColumnCount, PTS.FSKUPDATE fskupdRow, CalculatedColumn[] calculatedColumns) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; CellParaClientEntry[] arrayCellParaClients; VisualCollection cellVisualsCollection; int sourceIndex; QueryRowDetails( pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); // arrayFsCell lists cells in order different from one we want to maintain in visual collection. // before going to update visual collection it is necessary to reorder ascending by cell's column index. // knowing the following facts: // * total number of columns the row holds (including row spanned cells from previous rows) less or equal to tableColumnCount; // * total number of cells (including row spanned cells from previous rows) is less or equal to tableColumnCount; // * cells do not overlap - no two cells have the same column index; // * cells' column indices fall into the range [0, tableColumnCount - 1]; // it is possible to write custom and optimized sorting routine: // * iterate through arrayFsCell; // * for each item record its CellParaClient value into arrayCellParaClients[CellParaClient.ColumnIndex]; // once complete, arrayCellParaClients will contain CellParaClients in correct order. some entries however will be null // due to potential column spanning of cells. arrayCellParaClients = new CellParaClientEntry[tableColumnCount]; for (int iC = 0; iC < arrayFsCell.Length; ++iC) { CellParaClient cellParaClient; PTS.FSKUPDATE fskupdCell; int columnIndex; if (arrayFsCell[iC] == IntPtr.Zero) { // paginated case - cell may be null continue; } fskupdCell = (arrayUpdate[iC] != PTS.FSKUPDATE.fskupdInherited) ? arrayUpdate[iC] : fskupdRow; cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); columnIndex = cellParaClient.ColumnIndex; arrayCellParaClients[columnIndex].cellParaClient = cellParaClient; arrayCellParaClients[columnIndex].fskupdCell = fskupdCell; } cellVisualsCollection = rowVisual.Children; sourceIndex = 0; for (int columnIndex = 0; columnIndex < arrayCellParaClients.Length; ++columnIndex) { CellParaClient cellParaClient; double urCellOffset; PTS.FSKUPDATE fskupdCell; cellParaClient = arrayCellParaClients[columnIndex].cellParaClient; if (cellParaClient == null) { // paginated case - cell may be null continue; } fskupdCell = arrayCellParaClients[columnIndex].fskupdCell; if (fskupdCell != PTS.FSKUPDATE.fskupdNoChange) { urCellOffset = calculatedColumns[columnIndex].UrOffset; cellParaClient.ValidateVisual(); if (fskupdCell == PTS.FSKUPDATE.fskupdNew) { cellVisualsCollection.Insert(sourceIndex, cellParaClient.Visual); } else { Debug.Assert( cellParaClient.Visual != null // If the check below fails, then PTS cheats by reporting "ChangInside" for // a cell that in fact was re-Formatted. && VisualTreeHelper.GetParent(cellParaClient.Visual) != null ); SynchronizeCellVisualsCollection(cellVisualsCollection, sourceIndex, cellParaClient.Visual); } } sourceIndex++; } if (cellVisualsCollection.Count > sourceIndex) { cellVisualsCollection.RemoveRange( sourceIndex, cellVisualsCollection.Count - sourceIndex); } #if DEBUGDEBUG for (int columnIndex = 0, sourceIndex = 0; columnIndex < arrayCellParaClients.Length; ++columnIndex) { CellParaClient cellParaClient = arrayCellParaClients[columnIndex].cellParaClient; if (cellParaClient != null) { Debug.Assert(rowVisual.Children.IndexOf(cellParaClient.Visual) == sourceIndex); sourceIndex++; } } #endif // DEBUGDEBUG }
/// <summary> /// ValidateCalculatedColumns /// </summary> /// <remarks> /// Side effect: _durMinWidth and _durMaxWidth are also updated. /// </remarks> private void ValidateCalculatedColumns() { double totalPadding; int columns = Table.ColumnCount; if (_calculatedColumns == null) { _calculatedColumns = new CalculatedColumn[columns]; } else if (_calculatedColumns.Length != columns) { CalculatedColumn[] newCalculatedColumns = new CalculatedColumn[columns]; Array.Copy( _calculatedColumns, newCalculatedColumns, Math.Min(_calculatedColumns.Length, columns)); _calculatedColumns = newCalculatedColumns; } if (_calculatedColumns.Length > 0) { int i = 0; while (i < _calculatedColumns.Length && i < Table.Columns.Count) { _calculatedColumns[i].UserWidth = Table.Columns[i].Width; i++; } while (i < _calculatedColumns.Length) { _calculatedColumns[i].UserWidth = TableColumn.DefaultWidth; i++; } } _durMinWidth = _durMaxWidth = 0; for (int i = 0; i < _calculatedColumns.Length; ++i) { switch (_calculatedColumns[i].UserWidth.GridUnitType) { case (GridUnitType.Auto): // _calculatedColumns[i].ValidateAuto(1.0, 10e5); break; case (GridUnitType.Star): _calculatedColumns[i].ValidateAuto(1.0, 10e5); break; case (GridUnitType.Pixel): _calculatedColumns[i].ValidateAuto( _calculatedColumns[i].UserWidth.Value, _calculatedColumns[i].UserWidth.Value); break; default: Debug.Assert(false, "Unsupported unit type"); break; } _durMinWidth += _calculatedColumns[i].DurMinWidth; _durMaxWidth += _calculatedColumns[i].DurMaxWidth; } // Use durAvailable as width limit for MBP, and MaxWidth as height limit since height values will not be used MbpInfo mbpInfo = MbpInfo.FromElement(Paragraph.Element); totalPadding = Table.InternalCellSpacing * Table.ColumnCount + mbpInfo.Margin.Left + mbpInfo.Border.Left + mbpInfo.Padding.Left + mbpInfo.Padding.Right + mbpInfo.Border.Right + mbpInfo.Margin.Right; _durMinWidth += totalPadding; _durMaxWidth += totalPadding; }
private void ValidateRowVisualSimple( RowVisual rowVisual, IntPtr pfstablerow, PTS.FSKUPDATE fskupdRow, CalculatedColumn[] calculatedColumns) { PTS.FSKUPDATE[] arrayUpdate; IntPtr[] arrayFsCell; PTS.FSTABLEKCELLMERGE[] arrayTableCellMerge; VisualCollection cellVisualsCollection; int sourceIndex; QueryRowDetails( pfstablerow, out arrayFsCell, out arrayUpdate, out arrayTableCellMerge); cellVisualsCollection = rowVisual.Children; sourceIndex = 0; for (int iC = 0; iC < arrayFsCell.Length; ++iC) { CellParaClient cellParaClient; double urCellOffset; PTS.FSKUPDATE fskupdCell; if ( // paginated case - cell may be null arrayFsCell[iC] == IntPtr.Zero // exclude hanging cells || arrayTableCellMerge[iC] == PTS.FSTABLEKCELLMERGE.fskcellmergeMiddle || arrayTableCellMerge[iC] == PTS.FSTABLEKCELLMERGE.fskcellmergeLast ) { continue; } fskupdCell = (arrayUpdate[iC] != PTS.FSKUPDATE.fskupdInherited) ? arrayUpdate[iC] : fskupdRow; if (fskupdCell != PTS.FSKUPDATE.fskupdNoChange) { cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); urCellOffset = calculatedColumns[cellParaClient.ColumnIndex].UrOffset; cellParaClient.ValidateVisual(); if ( fskupdCell == PTS.FSKUPDATE.fskupdNew // PTS bug is a suspect here - this is a temp workaround: || VisualTreeHelper.GetParent(cellParaClient.Visual) == null ) { Visual currentParent = VisualTreeHelper.GetParent(cellParaClient.Visual) as Visual; if(currentParent != null) { ContainerVisual parent = currentParent as ContainerVisual; Invariant.Assert(parent != null, "parent should always derives from ContainerVisual"); parent.Children.Remove(cellParaClient.Visual); } cellVisualsCollection.Insert(sourceIndex, cellParaClient.Visual); } else { Debug.Assert( cellParaClient.Visual != null // If the check below fails, then PTS cheats by reporting "ChangInside" for // a cell that in fact was re-Formatted. && VisualTreeHelper.GetParent(cellParaClient.Visual) != null ); SynchronizeCellVisualsCollection(cellVisualsCollection, sourceIndex, cellParaClient.Visual); } } sourceIndex++; } if (cellVisualsCollection.Count > sourceIndex) { cellVisualsCollection.RemoveRange( sourceIndex, cellVisualsCollection.Count - sourceIndex); } #if DEBUGDEBUG for (int iC = 0, sourceIndex = 0; iC < arrayFsCell.Length; ++iC) { if ( arrayFsCell[iC] != IntPtr.Zero && arrayTableCellMerge[iC] != PTS.FSTABLEKCELLMERGE.fskcellmergeMiddle && arrayTableCellMerge[iC] != PTS.FSTABLEKCELLMERGE.fskcellmergeLast ) { CellParaClient cellParaClient = (CellParaClient)(PtsContext.HandleToObject(arrayFsCell[iC])); Debug.Assert(rowVisual.Children.IndexOf(cellParaClient.Visual) == sourceIndex); sourceIndex++; } } #endif // DEBUGDEBUG }