protected SizeD GetObjectSizeInPage(int pageColumn, int pageRow, PointD start) { PageSettings page = (PageSettings)DocumentHelper.CurrentPageSettings.Clone(); page.Column = pageColumn; page.Row = pageRow; PointD startOffset = GetContentStart(); PointD endOffset = GetContentEnd(); RectangleD objectRec = new RectangleD ( start.X + startOffset.X, start.Y + startOffset.Y, calculatedSize.WidthValue - startOffset.X - endOffset.X, calculatedSize.HeightValue - startOffset.Y - endOffset.Y ); objectRec.Intersect(page.GetPageRectangle()); return(objectRec.Size); }
private bool ResolveChildSizes(PointD start) { if (!allocatedSize.Height.HasValue && !allocatedSize.Width.HasValue) { return(true); } int i; double calcSize; double percentRatio; bool optimized; start.X += allocatedHPageFill; start.Y += allocatedVPageFill; PointD childStart = GetContentStart(start); PointD startOffset = GetContentStart(); PointD endOffset = GetContentEnd(); float innerOffset = GetInnerChildOffset(); ObjectStyle.ChildDistribution childDist = ChildDistribution; double [] totalSpace = null; double [] absoluteSpace = null; double [] relativeSpace = null; int childCount = Children.Count; int pageCount; int lastPageInd; int pageInd; List <PointD> childPositions = new List <PointD> (); if (childDist == ObjectStyle.ChildDistribution.Horizontal) { try { #region Initialize arrays and the total space used by the object in each page pageCount = Math.Max(distribution.RightColumn + 1, Children .Cast <FormDrawableObject> () .Select(child => child.Distribution.RightColumn + 1) .DefaultIfEmpty().Max()); totalSpace = new double [pageCount]; absoluteSpace = new double [pageCount]; relativeSpace = new double [pageCount]; for (i = 0; i <= distribution.RightColumn; i++) { totalSpace [i] = GetObjectSizeInPage(i, distribution.UpperRow, start).Width; } #endregion } catch (Exception ex) { throw new Exception("Exception while initializing the total space used by the horizontally aligned object", ex); } try { #region Calculate the space used in each page by each child object i = 0; PointD cursor = childStart; lastPageInd = distribution.LeftColumn; foreach (FormDrawableObject drawable in Children) { childPositions.Add(cursor); pageInd = drawable.Distribution.LeftColumn; if (drawable.AllocatedSize.RelativeWidth.HasValue) { relativeSpace [pageInd] += drawable.AllocatedSize.RelativeWidth.Value; } else if (drawable.AllocatedSize.Width.HasValue) { absoluteSpace [pageInd] += drawable.AllocatedSize.Width.Value; } cursor.X += drawable.AllocatedSize.WidthValue; if (lastPageInd != pageInd) { absoluteSpace [pageInd] += innerOffset; cursor.X += innerOffset; cursor.X += drawable.AllocatedHPageFill; } if (drawable.Distribution.GetColumnsUsed() > 1) { totalSpace [pageInd + 1] -= cursor.X % DocumentHelper.CurrentPageSettings.Width; } else if (i < childCount - 1) { absoluteSpace [pageInd] += innerOffset; cursor.X += innerOffset; } i++; lastPageInd = pageInd; } #endregion } catch (Exception ex) { throw new Exception("Exception while calculating the space used in each page by the horizontally aligned children", ex); } try { #region Check if we have to treat the object as "Mixed mode" if (!allocatedSize.Width.HasValue) { foreach (float rel in relativeSpace) { if (rel > 0f) { childDist = ObjectStyle.ChildDistribution.Mixed; } } } #endregion } catch (Exception ex) { throw new Exception("Exception while checking if we have to treat the horizontally aligned object as mixed mode", ex); } } if (childDist == ObjectStyle.ChildDistribution.Vertical) { try { #region Initialize arrays and the total space used by the object in each page pageCount = Math.Max(distribution.LowerRow + 1, Children .Cast <FormDrawableObject> () .Select(child => child.Distribution.LowerRow + 1) .DefaultIfEmpty().Max()); totalSpace = new double [pageCount]; absoluteSpace = new double [pageCount]; relativeSpace = new double [pageCount]; for (i = 0; i <= distribution.LowerRow; i++) { totalSpace [i] = GetObjectSizeInPage(Distribution.LeftColumn, i, start).Height; } #endregion } catch (Exception ex) { throw new Exception("Exception while initializing the total space used by the vertically aligned object", ex); } try { #region Calculate the space used in each page by each child object i = 0; PointD cursor = childStart; lastPageInd = distribution.UpperRow; foreach (FormDrawableObject drawable in Children) { childPositions.Add(cursor); pageInd = drawable.Distribution.UpperRow; if (drawable.AllocatedSize.RelativeHeight.HasValue) { relativeSpace [pageInd] += drawable.AllocatedSize.RelativeHeight.Value; } else if (drawable.AllocatedSize.Height.HasValue) { absoluteSpace [pageInd] += drawable.AllocatedSize.Height.Value; } cursor.Y += drawable.AllocatedSize.HeightValue; if (lastPageInd != pageInd) { absoluteSpace [pageInd] += innerOffset; cursor.Y += innerOffset; cursor.Y += drawable.AllocatedVPageFill; } if (drawable.Distribution.GetRowsUsed() > 1) { totalSpace [pageInd + 1] -= cursor.Y % DocumentHelper.CurrentPageSettings.Height; } else if (i < childCount - 1) { absoluteSpace [pageInd] += innerOffset; cursor.Y += innerOffset; } i++; lastPageInd = pageInd; } #endregion } catch (Exception ex) { throw new Exception("Exception while calculating the space used in each page by the vertically aligned children", ex); } try { #region Check if we have to treat the object as "Mixed mode" if (!allocatedSize.Height.HasValue) { foreach (float rel in relativeSpace) { if (rel > 0f) { childDist = ObjectStyle.ChildDistribution.Mixed; } } } #endregion } catch (Exception ex) { throw new Exception("Exception while checking if we have to treat the vertically aligned object as mixed mode", ex); } } switch (childDist) { case ObjectStyle.ChildDistribution.Horizontal: try { #region Optimize relative sizes for (i = 0, optimized = false; i < childCount && !optimized; i++) { optimized = true; foreach (FormDrawableObject drawable in Children) { if (!drawable.AllocatedSize.RelativeWidth.HasValue || !drawable.AllocatedSize.Width.HasValue) { continue; } pageInd = drawable.Distribution.LeftColumn; // Find out the percentage of the space left for relative sizing percentRatio = (totalSpace [pageInd] - absoluteSpace [pageInd]) * 100f / totalSpace [pageInd]; // Calculate the coeficient for percent translation percentRatio /= relativeSpace [pageInd]; percentRatio = Math.Min(percentRatio, 1f); calcSize = (float)Math.Round(totalSpace [pageInd] * Math.Min(drawable.AllocatedSize.RelativeWidthValue * percentRatio, 100f) / 100f, MidpointRounding.AwayFromZero); if (calcSize <= drawable.AllocatedSize.Width) { absoluteSpace [pageInd] += drawable.AllocatedSize.WidthValue; relativeSpace [pageInd] -= drawable.AllocatedSize.RelativeWidthValue; drawable.AllocatedSize.RelativeWidth = null; optimized = false; } } } #endregion } catch (Exception ex) { throw new Exception("Exception while optimizing the relative sizes of the horizontally aligned object", ex); } try { #region Calculate relative sizes lastPageInd = 0; i = 0; foreach (FormDrawableObject drawable in Children) { if (drawable.AllocatedSize.RelativeHeight.HasValue && calculatedSize.Height.HasValue) { drawable.CalculatedSize.Height = (float)Math.Round( Math.Max(calculatedSize.HeightValue - startOffset.Y - endOffset.Y, 0f) * Math.Min(drawable.AllocatedSize.RelativeHeightValue, 100f) / 100f, MidpointRounding.AwayFromZero); } else { drawable.CalculatedSize.Height = drawable.AllocatedSize.Height; } pageInd = drawable.Distribution.LeftColumn; if (totalSpace [pageInd] == 0f) { i++; continue; } if (drawable.AllocatedSize.RelativeWidth.HasValue) { // Find out the percentage of the space left for relative sizing percentRatio = (totalSpace [pageInd] - absoluteSpace [pageInd]) * 100f / totalSpace [pageInd]; // Calculate the coeficient for percent translation percentRatio /= relativeSpace [pageInd]; percentRatio = Math.Min(percentRatio, 1f); relativeSpace [pageInd] -= drawable.AllocatedSize.RelativeWidthValue; if (relativeSpace [pageInd] > 0f || relativeSpace.Length - 1 == pageInd) { calcSize = (float)Math.Round((totalSpace [pageInd] * Math.Min(drawable.AllocatedSize.RelativeWidthValue * percentRatio, 100f) / 100f), MidpointRounding.AwayFromZero); drawable.CalculatedSize.Width = calcSize; } else { drawable.CalculatedSize.Width = totalSpace [pageInd] - absoluteSpace [pageInd]; } absoluteSpace [pageInd] += drawable.CalculatedSize.WidthValue; } else { drawable.CalculatedSize.Width = drawable.AllocatedSize.Width; } if (i > 0 && lastPageInd != pageInd) { drawable.CalculatedHPageFill = totalSpace [lastPageInd] - absoluteSpace [lastPageInd]; } else { drawable.CalculatedHPageFill = 0f; } if (!drawable.OnSizeCalculated(childPositions [i])) { return(false); } lastPageInd = drawable.Distribution.RightColumn; i++; } #endregion } catch (Exception ex) { throw new Exception("Exception while calculating the relative sizes of the horizontally aligned object", ex); } break; case ObjectStyle.ChildDistribution.Vertical: try { #region Optimize relative sizes for (i = 0, optimized = false; i < childCount && !optimized; i++) { optimized = true; foreach (FormDrawableObject drawable in Children) { if (!drawable.AllocatedSize.RelativeHeight.HasValue || !drawable.AllocatedSize.Height.HasValue) { continue; } pageInd = drawable.Distribution.UpperRow; // Find out the percentage of the space left for relative sizing percentRatio = (totalSpace [pageInd] - absoluteSpace [pageInd]) * 100f / totalSpace [pageInd]; // Calculate the coeficient for percent translation percentRatio /= relativeSpace [pageInd]; percentRatio = Math.Min(percentRatio, 1f); calcSize = (float)Math.Round(totalSpace [pageInd] * Math.Min(drawable.AllocatedSize.RelativeHeightValue * percentRatio, 100f) / 100f, MidpointRounding.AwayFromZero); if (calcSize <= drawable.AllocatedSize.Height) { absoluteSpace [pageInd] += drawable.AllocatedSize.HeightValue; relativeSpace [pageInd] -= drawable.AllocatedSize.RelativeHeightValue; drawable.AllocatedSize.RelativeHeight = null; optimized = false; } } } #endregion } catch (Exception ex) { throw new Exception("Exception while optimizing the relative sizes of the vertically aligned object", ex); } try { #region Calculate relative sizes lastPageInd = 0; i = 0; foreach (FormDrawableObject drawable in Children) { if (drawable.AllocatedSize.RelativeWidth.HasValue && calculatedSize.Width.HasValue) { drawable.CalculatedSize.Width = (float)Math.Round( Math.Max(calculatedSize.WidthValue - startOffset.X - endOffset.X, 0f) * Math.Min(drawable.AllocatedSize.RelativeWidthValue, 100f) / 100f, MidpointRounding.AwayFromZero); } else { drawable.CalculatedSize.Width = drawable.AllocatedSize.Width; } pageInd = drawable.Distribution.UpperRow; if (totalSpace [pageInd] == 0f) { i++; continue; } if (drawable.AllocatedSize.RelativeHeight.HasValue) { // Find out the percentage of the space left for relative sizing percentRatio = (totalSpace [pageInd] - absoluteSpace [pageInd]) * 100f / totalSpace [pageInd]; // Calculate the coeficient for percent translation percentRatio /= relativeSpace [pageInd]; percentRatio = Math.Min(percentRatio, 1f); relativeSpace [pageInd] -= drawable.AllocatedSize.RelativeHeightValue; if (relativeSpace [pageInd] > 0f || relativeSpace.Length - 1 == pageInd) { calcSize = (float)Math.Round((totalSpace [pageInd] * Math.Min(drawable.AllocatedSize.RelativeHeightValue * percentRatio, 100f) / 100f), MidpointRounding.AwayFromZero); drawable.CalculatedSize.Height = calcSize; } else { drawable.CalculatedSize.Height = totalSpace [pageInd] - absoluteSpace [pageInd]; } absoluteSpace [pageInd] += drawable.CalculatedSize.HeightValue; } else { drawable.CalculatedSize.Height = drawable.AllocatedSize.Height; } if (i > 0 && lastPageInd != pageInd) { drawable.CalculatedVPageFill = totalSpace [lastPageInd] - absoluteSpace [lastPageInd]; } else { drawable.CalculatedVPageFill = 0f; } if (!drawable.OnSizeCalculated(childPositions [i])) { return(false); } lastPageInd = drawable.Distribution.LowerRow; i++; } #endregion } catch (Exception ex) { throw new Exception("Exception while calculating the relative sizes of the vertically aligned object", ex); } break; case ObjectStyle.ChildDistribution.Mixed: try { #region Calculate relative sizes foreach (FormDrawableObject drawable in Children) { PageSettings pSettings = (PageSettings)DocumentHelper.CurrentPageSettings.Clone(); pSettings.Column = drawable.Distribution.LeftColumn; pSettings.Row = drawable.Distribution.UpperRow; RectangleD pRect = pSettings.GetPageRectangle(); pRect.Inflate(-endOffset.X, -endOffset.Y); if (drawable.Distribution.GetColumnsUsed() == 1 && drawable.AllocatedSize.RelativeWidth.HasValue && calculatedSize.Width.HasValue) { calcSize = (float)Math.Round( Math.Max(calculatedSize.WidthValue - startOffset.X - endOffset.X, 0f) * Math.Min(drawable.AllocatedSize.RelativeWidthValue, 100f) / 100f, MidpointRounding.AwayFromZero); RectangleD temp = new RectangleD(childStart, new SizeD(calcSize, 1f)); temp.X += drawable.AllocatedHPageFill; temp.Intersect(pRect); calcSize = temp.Width; } else { calcSize = drawable.AllocatedSize.WidthValue; } drawable.CalculatedSize.Width = calcSize; drawable.CalculatedHPageFill = drawable.AllocatedHPageFill; if (drawable.Distribution.GetRowsUsed() == 1 && drawable.AllocatedSize.RelativeHeight.HasValue && calculatedSize.Height.HasValue) { calcSize = (float)Math.Round( Math.Max(calculatedSize.HeightValue - startOffset.Y - endOffset.Y, 0f) * Math.Min(drawable.AllocatedSize.RelativeHeightValue, 100f) / 100f, MidpointRounding.AwayFromZero); RectangleD temp = new RectangleD(childStart, new SizeD(1f, calcSize)); temp.Y += drawable.AllocatedVPageFill; temp.Intersect(pRect); calcSize = temp.Height; } else { calcSize = drawable.AllocatedSize.HeightValue; } drawable.CalculatedSize.Height = calcSize; drawable.CalculatedVPageFill = drawable.AllocatedVPageFill; if (!drawable.OnSizeCalculated(childStart)) { return(false); } } #endregion } catch (Exception ex) { throw new Exception("Exception while calculating the relative sizes of the mixed mode object", ex); } break; } return(true); }