File: System\Windows\Documents\FixedSOMTable.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Windows.Media;
 
/*++                                            
    Description:
        This class reprsents a table on the page
--*/
 
namespace System.Windows.Documents
{
    internal sealed class FixedSOMTable : FixedSOMPageElement
    {
        //--------------------------------------------------------------------
        //
        // Constructors
        //
        //---------------------------------------------------------------------
        
        #region Constructors
        public FixedSOMTable(FixedSOMPage page) : base(page)
        {
            _numCols = 0;
        }
        #endregion Constructors
 
        //--------------------------------------------------------------------
        //
        // Public Methods
        //
        //---------------------------------------------------------------------
 
        #region Public Methods
#if DEBUG        
        public override void Render(DrawingContext dc, string label, DrawDebugVisual debugVisual)
        {
            Pen pen = new Pen(Brushes.Green, 5);
            Rect rect = _boundingRect;
            dc.DrawRectangle(null, pen , rect);
 
            FormattedText ft = new FormattedText(label, 
                                        System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS,
                                        FlowDirection.LeftToRight,
                                        new Typeface("Courier New"), 
                                        20,
                                        Brushes.Blue,
                                        MS.Internal.FontCache.Util.PixelsPerDip);
            Point labelLocation = new Point(rect.Left-25, (rect.Bottom + rect.Top)/2 - 10);
          //  dc.DrawText(ft, labelLocation);            
            
            for (int i = 0; i < _semanticBoxes.Count; i++)
            {
                _semanticBoxes[i].Render(dc, $"{label} {i}",debugVisual);
            }
        }
#endif
        public void AddRow(FixedSOMTableRow row)
        {
            base.Add(row);
            int colCount = row.SemanticBoxes.Count;
            if (colCount > _numCols)
            {
                _numCols = colCount;
            }
        }
 
        public bool AddContainer(FixedSOMContainer container)
        {
            Rect bounds = container.BoundingRect;
 
            
            //Allow couple pixels margin
            double verticalOverlap = bounds.Height * 0.2;
            double horizontalOverlap = bounds.Width * 0.2;
            bounds.Inflate(-horizontalOverlap,-verticalOverlap);
 
            if (this.BoundingRect.Contains(bounds))
            {
                foreach (FixedSOMTableRow row in this.SemanticBoxes)
                {
                    if (row.BoundingRect.Contains(bounds))
                    {
                        foreach (FixedSOMTableCell cell in row.SemanticBoxes)
                        {
                            if (cell.BoundingRect.Contains(bounds))
                            {
                                cell.AddContainer(container);
                                FixedSOMFixedBlock block = container as FixedSOMFixedBlock;
                                if (block != null)
                                {
                                    if (block.IsRTL)
                                    {
                                        _RTLCount++;
                                    }
                                    else
                                    {
                                        _LTRCount++;
                                    }
                                }
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
 
 
        public override void SetRTFProperties(FixedElement element)
        {
            if (element.Type == typeof(Table))
            {
                element.SetValue(Table.CellSpacingProperty, 0.0);
            }
        }
 
        
        #endregion Public Methods
 
        #region Public Properties
        public override bool IsRTL
        {
            get
            {
                return _RTLCount > _LTRCount;
            }
        }
        #endregion Public Properties
 
        #region Internal Properties
        internal override FixedElement.ElementType[] ElementTypes
        {
            get
            {
                return new FixedElement.ElementType[2] { FixedElement.ElementType.Table, FixedElement.ElementType.TableRowGroup };
            }
        }
 
        internal bool IsEmpty
        {
            get
            {
                foreach (FixedSOMTableRow row in this.SemanticBoxes)
                {
                    if (!row.IsEmpty)
                    {
                        return false;
                    }
                }
                return true;
            }
        }
 
        internal bool IsSingleCelled
        {
            get
            {
                if (this.SemanticBoxes.Count == 1)
                {
                    FixedSOMTableRow row = this.SemanticBoxes[0] as FixedSOMTableRow;
                    Debug.Assert(row != null);
                    return (row.SemanticBoxes.Count == 1);
                }
                return false;
            }
        }
 
 
        #endregion Internal Properties
 
        #region Internal methods
        internal void DeleteEmptyRows()
        {
            for (int i=0; i<this.SemanticBoxes.Count;)
            {
                FixedSOMTableRow row = this.SemanticBoxes[i] as FixedSOMTableRow;
                Debug.Assert(row != null);
                if (row != null && row.IsEmpty && row.BoundingRect.Height < _minRowHeight)
                {
                    this.SemanticBoxes.RemoveAt(i);
                }
                else
                {
                    i++;
                }
            }
        }
 
        //Deletes an entire column if its empty
        //Sets column spans
 
        internal void DeleteEmptyColumns()
        {
            int nRows = this.SemanticBoxes.Count;
            int[] indexInRow = new int[nRows];
 
            while (true)
            {
                double nextCol = double.MaxValue;
                bool deleteCol = true;
                int r;
                for (r = 0; r < nRows; r++)
                {
                    FixedSOMTableRow row = (FixedSOMTableRow)(this.SemanticBoxes[r]);
                    int idx = indexInRow[r];
                    FixedSOMTableCell cell;
 
                    deleteCol = deleteCol && idx < row.SemanticBoxes.Count;
                    if (deleteCol)
                    {
                        cell = (FixedSOMTableCell)row.SemanticBoxes[idx];
                        // is empty?
                        deleteCol = cell.IsEmpty && cell.BoundingRect.Width < _minColumnWidth;
                    }
 
                    // where does next column start?
                    if (idx + 1 < row.SemanticBoxes.Count)
                    {
                        cell = (FixedSOMTableCell)row.SemanticBoxes[idx+1];
                        double cellStart = cell.BoundingRect.Left;
 
                        if (cellStart < nextCol)
                        {
                            if (nextCol != double.MaxValue)
                            {
                                // can't delete colums where not all have same width
                                deleteCol = false;
                            }
                            nextCol = cellStart;
                        }
                        else if (cellStart > nextCol)
                        {
                            deleteCol = false;
                        }
                    }
                }
 
                if (deleteCol)
                {
                    for (r = 0; r < nRows; r++)
                    {
                        FixedSOMTableRow row = (FixedSOMTableRow)(this.SemanticBoxes[r]);
                        row.SemanticBoxes.RemoveAt(indexInRow[r]);
                    }
 
                    if (nextCol == double.MaxValue)
                    {
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
                // are we done?
                if (nextCol == double.MaxValue)
                {
                    break;
                }
                // increment ColumnSpans, indexInRow
                for (r = 0; r < nRows; r++)
                {
                    FixedSOMTableRow row = (FixedSOMTableRow)(this.SemanticBoxes[r]);
                    int idx = indexInRow[r];
                    if (idx + 1 < row.SemanticBoxes.Count && row.SemanticBoxes[idx + 1].BoundingRect.Left == nextCol)
                    {
                        indexInRow[r] = idx + 1;
                    }
                    else
                    {
                        ((FixedSOMTableCell)row.SemanticBoxes[idx]).ColumnSpan++;
                    }
                }
            }
        }
 
          
 
        #endregion Internal methods
 
        //--------------------------------------------------------------------
        //
        // Private Fields
        //
        //---------------------------------------------------------------------
        #region Private Fields
        const double _minColumnWidth = 5; // empty columns narrower than this will be deleted
        const double _minRowHeight = 10; //empty rows smaller than this will be deleted
 
        private int _RTLCount;
        private int _LTRCount;
 
        int _numCols;
 
        #endregion Private Fields
    }
}