public abstract SizeF GetSize(Graphics g, DocumentMetrics metrics);
/// <summary> /// Make first calculations to know exactly what we can print on each sheet /// </summary> /// <param name="g"></param> /// <param name="metrics"></param> public void Initialize(Graphics g, DocumentMetrics metrics) { this.metrics = metrics; #region Take care of set blocks if (SheetHeader != null) { float headerHeight = SheetHeader.GetSize(g, metrics).Height; SheetHeader.Rectangle = new RectangleF(metrics.LeftMargin, metrics.TopMargin, metrics.PrintAbleWidth, headerHeight); metrics.TopMargin += (int)Math.Ceiling(headerHeight); } if (TitlePrintBlock != null) { float titleHeight = TitlePrintBlock.GetSize(g, metrics).Height; TitlePrintBlock.Rectangle = new RectangleF(metrics.LeftMargin, metrics.TopMargin, metrics.PrintAbleWidth, titleHeight); } if (SheetFooter != null) { float footerHeight = SheetFooter.GetSize(g, metrics).Height; metrics.BottomMargin += (int)Math.Ceiling(footerHeight); float footerY = metrics.TopMargin + metrics.PrintAbleHeight; SheetFooter.Rectangle = new RectangleF(metrics.LeftMargin, footerY, metrics.PrintAbleWidth, footerHeight); } #endregion columnWidths = new float[GridView.Columns.Count]; colSelector = new Func <DataGridViewColumn, bool>(column => (MustPrintSelectedColumns && column.DataGridView.SelectedColumns.Count > 0) ? column.Selected : column.Visible); float gridWidth = 0; // calculate the grid width to know the difference with a sheet width, // it's usefull to determinate a scale foreach (var column in GridView.Columns.OfType <DataGridViewColumn>() .Where(colSelector)) { columnWidths[column.Index] = column.Width(g); gridWidth += columnWidths[column.Index]; } // we fix the scale to 1 if user doesn't need to zoom out the grid or if // the gridwidth is lower thant sheet width scale = (!MustFitColumnsToPage || gridWidth < metrics.PrintAbleWidth) ? 1 : metrics.PrintAbleWidth / gridWidth; columnHeaderHeight = GridView.HeaderHeight(g, scale); // let's go to set the partition splits List <int> firstColumnsOnPartition = new List <int>(); float tmpWidth = 0; foreach (var column in GridView.Columns.OfType <DataGridViewColumn>() .Where(colSelector)) { columnWidths[column.Index] *= scale; tmpWidth += columnWidths[column.Index]; if (tmpWidth > metrics.PrintAbleWidth || column.Index == 0) { firstColumnsOnPartition.Insert(0, column.Index); tmpWidth = columnWidths[column.Index]; } } firstColumnsOnPartition.Reverse(); // let's go to set the level splits rowSelector = new Func <DataGridViewRow, bool>(row => (MustPrintSelectedRows && row.DataGridView.SelectedRows.Count > 0) ? row.Selected : row.Visible); rowsHeights = new float[GridView.Rows.Count]; List <int> firstRowsOnPartition = new List <int>(); // we have to set the first visible row outside of the loop // cause we want to take care about the possible set Title block int firstVisibleRowIndex = GridView.Rows.OfType <DataGridViewRow>() .Where(rowSelector).First().Index; firstRowsOnPartition.Insert(0, firstVisibleRowIndex); rowsHeights[firstVisibleRowIndex] = GridView.Rows[firstVisibleRowIndex].RowHeight(g); float tmpHeight = rowsHeights[firstVisibleRowIndex]; if (TitlePrintBlock != null) { tmpHeight += TitlePrintBlock.Rectangle.Height; } // skip the first visible row cause it is already in firstrows (see above) foreach (var row in GridView.Rows.OfType <DataGridViewRow>() .Where(rowSelector).Skip(1)) { rowsHeights[row.Index] = row.RowHeight(g, scale); tmpHeight += rowsHeights[row.Index]; // warn to take care about the column headers if (tmpHeight >= metrics.PrintAbleHeight - columnHeaderHeight) { firstRowsOnPartition.Insert(0, row.Index); tmpHeight = rowsHeights[row.Index]; } } firstRowsOnPartition.Reverse(); // now that it is calculated, we can fix definitely firstRows and firstColumns in arrays firstRows = firstRowsOnPartition.ToArray(); firstColumns = firstColumnsOnPartition.ToArray(); levels = new Dictionary <int, IEnumerable <Partition> >(firstRows.Length); codes = new Dictionary <CodeEnum, string>(); codes[CodeEnum.SheetsCount] = SheetsCount.ToString(); codes[CodeEnum.Date] = DateTime.Now.ToShortDateString(); codes[CodeEnum.Time] = DateTime.Now.ToShortTimeString(); IsInitialized = true; }