/** * Creates a Cell with these attributes. * @param rowAttributes * @return a cell based on these attributes. * @throws BadElementException */ public Cell CreateCell(SimpleCell rowAttributes) { Cell cell = new Cell(); cell.CloneNonPositionParameters(rowAttributes); cell.SoftCloneNonPositionParameters(this); cell.Colspan = colspan; cell.HorizontalAlignment = horizontalAlignment; cell.VerticalAlignment = verticalAlignment; cell.UseAscender = useAscender; cell.UseBorderPadding = useBorderPadding; cell.UseDescender = useDescender; foreach (IElement element in content) { cell.AddElement(element); } return cell; }
// methods to set the membervariables /** * Adds an element to this Cell. * <P> * Remark: you can't add ListItems, Rows, Cells, * JPEGs, GIFs or PNGs to a Cell. * * @param element The Element to add * @throws BadElementException if the method was called with a ListItem, Row or Cell */ /// <summary> /// Adds an element to this Cell. /// </summary> /// <remarks> /// You can't add ListItems, Rows, Cells, /// JPEGs, GIFs or PNGs to a Cell. /// </remarks> /// <param name="element">the Element to add</param> public void AddElement(IElement element) { if (IsTable()) { Table table = (Table) arrayList[0]; Cell tmp = new Cell(element); tmp.Border = NO_BORDER; tmp.Colspan = table.Columns; table.AddCell(tmp); return; } switch (element.Type) { case Element.LISTITEM: case Element.ROW: case Element.CELL: throw new BadElementException("You can't add listitems, rows or cells to a cell."); case Element.JPEG: case Element.IMGRAW: case Element.IMGTEMPLATE: arrayList.Add(element); break; case Element.LIST: if (float.IsNaN(this.Leading)) { leading = ((List) element).TotalLeading; } if (((List) element).IsEmpty()) return; arrayList.Add(element); return; case Element.ANCHOR: case Element.PARAGRAPH: case Element.PHRASE: if (float.IsNaN(leading)) { leading = ((Phrase) element).Leading; } if (((Phrase) element).IsEmpty()) return; arrayList.Add(element); return; case Element.CHUNK: if (((Chunk) element).IsEmpty()) return; arrayList.Add(element); return; case Element.TABLE: Table table = new Table(3); float[] widths = new float[3]; widths[1] = ((Table)element).Width; switch (((Table)element).Alignment) { case Element.ALIGN_LEFT: widths[0] = 0f; widths[2] = 100f - widths[1]; break; case Element.ALIGN_CENTER: widths[0] = (100f - widths[1]) / 2f; widths[2] = widths[0]; break; case Element.ALIGN_RIGHT: widths[0] = 100f - widths[1]; widths[2] = 0f; break; } table.Widths = widths; Cell tmp; if (arrayList.Count == 0) { table.AddCell(Cell.DummyCell); } else { tmp = new Cell(); tmp.Border = NO_BORDER; tmp.Colspan = 3; foreach (IElement ele in arrayList) { tmp.Add(ele); } table.AddCell(tmp); } tmp = new Cell(); tmp.Border = NO_BORDER; table.AddCell(tmp); table.InsertTable((Table)element); tmp = new Cell(); tmp.Border = NO_BORDER; table.AddCell(tmp); table.AddCell(Cell.DummyCell); Clear(); arrayList.Add(table); return; default: arrayList.Add(element); break; } }
/// <summary> /// Adds a Cell to the Table. /// </summary> /// <param name="cell">a Cell</param> public void AddCell(Cell cell) { try { AddCell(cell, curPosition); } catch (BadElementException) { // don't add the cell } }
/// <summary> /// Adds a Cell to the Table. /// </summary> /// <param name="content">a Phrase</param> /// <param name="location">a Point</param> public void AddCell(Phrase content, Point location) { Cell cell = new Cell(content); cell.Border = defaultCell.Border; cell.BorderWidth = defaultCell.BorderWidth; cell.BorderColor = defaultCell.BorderColor; cell.BackgroundColor = defaultCell.BackgroundColor; cell.HorizontalAlignment = defaultCell.HorizontalAlignment; cell.VerticalAlignment = defaultCell.VerticalAlignment; cell.Colspan = defaultCell.Colspan; cell.Rowspan = defaultCell.Rowspan; AddCell(cell, location); }
// methods to add content to the table /// <summary> /// Adds a Cell to the Table at a certain row and column. /// </summary> /// <param name="aCell">The Cell to add</param> /// <param name="row">The row where the Cell will be added</param> /// <param name="column">The column where the Cell will be added</param> public void AddCell(Cell aCell, int row, int column) { AddCell(aCell, new Point(row,column)); }
/// <summary> /// Adds a Cell to the Table at a certain location. /// </summary> /// <param name="aCell">The Cell to add</param> /// <param name="aLocation">The location where the Cell will be added</param> public void AddCell(Cell aCell, object aLocation) { Point p; if (aCell == null) throw new Exception("addCell - cell has null-value"); if (aLocation == null) throw new Exception("addCell - point has null-value"); else p = (Point)aLocation; if (aCell.IsTable()) { IEnumerator i = aCell.Elements.GetEnumerator(); i.MoveNext(); InsertTable((Table)i.Current, p); } if (p.X < 0) throw new BadElementException("row coordinate of location must be >= 0"); if ((p.Y <= 0) && (p.Y > columns)) throw new BadElementException("column coordinate of location must be >= 0 and < nr of columns"); if (!IsValidLocation(aCell, p)) throw new BadElementException("Adding a cell at the location (" + p.X + "," + p.Y + ") with a colspan of " + aCell.Colspan + " and a rowspan of " + aCell.Rowspan + " is illegal (beyond boundaries/overlapping)."); if (aCell.Border == UNDEFINED) aCell.Border = defaultCell.Border; aCell.Fill(); PlaceCell(rows, aCell, p); CurrentLocationToNextValidPosition = p; }
/// <summary> /// Inserts a Cell in a cell-array and reserves cells defined by row-/colspan. /// </summary> /// <param name="someRows">some rows</param> /// <param name="aCell">the cell that has to be inserted</param> /// <param name="aPosition">the position where the cell has to be placed</param> private void PlaceCell(ArrayList someRows, Cell aCell, Point aPosition) { int i; Row row = null; int rowCount = aPosition.X + aCell.Rowspan - someRows.Count; AssumeTableDefaults(aCell); if ( (aPosition.X + aCell.Rowspan) > someRows.Count ) { //create new rows ? for (i = 0; i < rowCount; i++) { row = new Row(columns); someRows.Add(row); } } // reserve cell in rows below for (i = aPosition.X + 1; i < (aPosition.X + aCell.Rowspan); i++) { if ( !((Row) someRows[i]).Reserve(aPosition.Y, aCell.Colspan)) { // should be impossible to come here :-) throw new Exception("addCell - error in reserve"); } } row = (Row) someRows[aPosition.X]; row.AddElement(aCell, aPosition.Y); }
/// <summary> /// check if Cell 'fits' the table. /// </summary> /// <remarks> /// <UL><LI/>rowspan/colspan not beyond borders /// <LI/>spanned cell don't overlap existing cells</UL> /// </remarks> /// <param name="aCell">the cell that has to be checked</param> /// <param name="aLocation">the location where the cell has to be placed</param> /// <returns></returns> private bool IsValidLocation(Cell aCell, Point aLocation) { // rowspan not beyond last column if ( aLocation.X < rows.Count ) { // if false : new location is already at new, not-yet-created area so no check if ((aLocation.Y + aCell.Colspan) > columns) { return false; } int difx = ((rows.Count - aLocation.X) > aCell.Rowspan) ? aCell.Rowspan : rows.Count - aLocation.X; int dify = ((columns - aLocation.Y) > aCell.Colspan) ? aCell.Colspan : columns - aLocation.Y; // no other content at cells targetted by rowspan/colspan for (int i=aLocation.X; i < (aLocation.X + difx); i++) { for (int j=aLocation.Y; j < (aLocation.Y + dify); j++) { if ( ((Row) rows[i]).IsReserved(j) == true ) { return false; } } } } else { if ((aLocation.Y + aCell.Colspan) > columns) { return false; } } return true; }
// methods /// <summary> /// Sets the unset cell properties to be the table defaults. /// </summary> /// <param name="aCell">The cell to set to table defaults as necessary.</param> private void AssumeTableDefaults(Cell aCell) { if (aCell.Border == Rectangle.UNDEFINED) { aCell.Border = defaultCell.Border; } if (aCell.BorderWidth == Rectangle.UNDEFINED) { aCell.BorderWidth = defaultCell.BorderWidth; } if (aCell.BorderColor == null) { aCell.BorderColor = defaultCell.BorderColor; } if (aCell.BackgroundColor == null) { aCell.BackgroundColor = defaultCell.BackgroundColor; } if (aCell.HorizontalAlignment == Element.ALIGN_UNDEFINED) { aCell.HorizontalAlignment = defaultCell.HorizontalAlignment; } if (aCell.VerticalAlignment == Element.ALIGN_UNDEFINED) { aCell.VerticalAlignment = defaultCell.VerticalAlignment; } }
/// <summary> /// Deletes a certain column has been deleted. /// </summary> /// <param name="column">the number of the column to delete</param> internal void DeleteColumn(int column) { if ((column >= columns) || (column < 0)) { throw new Exception("getCell at illegal index : " + column); } columns--; bool[] newReserved = new bool[columns]; Object[] newCells = new Cell[columns]; for (int i = 0; i < column; i++) { newReserved[i] = reserved[i]; newCells[i] = cells[i]; if (newCells[i] != null && (i + ((Cell) newCells[i]).Colspan > column)) { ((Cell) newCells[i]).Colspan = ((Cell) cells[i]).Colspan - 1; } } for (int i = column; i < columns; i++) { newReserved[i] = reserved[i + 1]; newCells[i] = cells[i + 1]; } if (cells[column] != null && ((Cell) cells[column]).Colspan > 1) { newCells[column] = cells[column]; ((Cell) newCells[column]).Colspan = ((Cell) newCells[column]).Colspan - 1; } reserved = newReserved; cells = newCells; }
// constructors /** * Constructs a <CODE>PdfCell</CODE>-object. * * @param cell the original <CODE>Cell</CODE> * @param rownumber the number of the <CODE>Row</CODE> the <CODE>Cell</CODE> was in. * @param left the left border of the <CODE>PdfCell</CODE> * @param right the right border of the <CODE>PdfCell</CODE> * @param top the top border of the <CODE>PdfCell</CODE> * @param cellspacing the cellspacing of the <CODE>Table</CODE> * @param cellpadding the cellpadding of the <CODE>Table</CODE> */ public PdfCell(Cell cell, int rownumber, float left, float right, float top, float cellspacing, float cellpadding) : base(left, top, right, top) { // copying the other Rectangle attributes from class Cell CloneNonPositionParameters(cell); this.cellpadding = cellpadding; this.cellspacing = cellspacing; this.verticalAlignment = cell.VerticalAlignment; this.useAscender = cell.UseAscender; this.useDescender = cell.UseDescender; this.useBorderPadding = cell.UseBorderPadding; // initialisation of some parameters PdfChunk chunk; PdfChunk overflow; lines = new ArrayList(); images = new ArrayList(); leading = cell.Leading; int alignment = cell.HorizontalAlignment; left += cellspacing + cellpadding; right -= cellspacing + cellpadding; left += GetBorderWidthInside(LEFT_BORDER); right -= GetBorderWidthInside(RIGHT_BORDER); contentHeight = 0; rowspan = cell.Rowspan; ArrayList allActions; int aCounter; // we loop over all the elements of the cell foreach (IElement ele in cell.Elements) { switch (ele.Type) { case Element.JPEG: case Element.JPEG2000: case Element.JBIG2: case Element.IMGRAW: case Element.IMGTEMPLATE: AddImage((Image)ele, left, right, 0.4f * leading, alignment); break; // if the element is a list case Element.LIST: if (line != null && line.Size > 0) { line.ResetAlignment(); AddLine(line); } // we loop over all the listitems AddList((List)ele, left, right, alignment); line = new PdfLine(left, right, alignment, leading); break; // if the element is something else default: allActions = new ArrayList(); ProcessActions(ele, null, allActions); aCounter = 0; float currentLineLeading = leading; float currentLeft = left; float currentRight = right; if (ele is Phrase) { currentLineLeading = ((Phrase) ele).Leading; } if (ele is Paragraph) { Paragraph p = (Paragraph) ele; currentLeft += p.IndentationLeft; currentRight -= p.IndentationRight; } if (line == null) { line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); } // we loop over the chunks ArrayList chunks = ele.Chunks; if (chunks.Count == 0) { AddLine(line); // add empty line - all cells need some lines even if they are empty line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); } else { foreach (Chunk c in chunks) { chunk = new PdfChunk(c, (PdfAction)allActions[aCounter++]); while ((overflow = line.Add(chunk)) != null) { AddLine(line); line = new PdfLine(currentLeft, currentRight, alignment, currentLineLeading); chunk = overflow; } } } // if the element is a paragraph, section or chapter, we reset the alignment and add the line switch (ele.Type) { case Element.PARAGRAPH: case Element.SECTION: case Element.CHAPTER: line.ResetAlignment(); FlushCurrentLine(); break; } break; } } FlushCurrentLine(); if (lines.Count > cell.MaxLines) { while (lines.Count > cell.MaxLines) { RemoveLine(lines.Count - 1); } if (cell.MaxLines > 0) { String more = cell.ShowTruncation; if (more != null && more.Length > 0) { // Denote that the content has been truncated lastLine = (PdfLine) lines[lines.Count - 1]; if (lastLine.Size >= 0) { PdfChunk lastChunk = lastLine.GetChunk(lastLine.Size - 1); float moreWidth = new PdfChunk(more, lastChunk).Width; while (lastChunk.ToString().Length > 0 && lastChunk.Width + moreWidth > right - left) { // Remove characters to leave room for the 'more' indicator lastChunk.Value = lastChunk.ToString().Substring(0, lastChunk.Length - 1); } lastChunk.Value = lastChunk.ToString() + more; } else { lastLine.Add(new PdfChunk(new Chunk(more), null)); } } } } // we set some additional parameters if (useDescender && lastLine != null) { contentHeight -= lastLine.Descender; } // adjust first line height so that it touches the top if (lines.Count > 0) { firstLine = (PdfLine) lines[0]; float firstLineRealHeight = FirstLineRealHeight; contentHeight -= firstLine.Height; firstLine.height = firstLineRealHeight; contentHeight += firstLineRealHeight; } float newBottom = top - contentHeight - (2f * Cellpadding) - (2f * Cellspacing); newBottom -= GetBorderWidthInside(TOP_BORDER) + GetBorderWidthInside(BOTTOM_BORDER); Bottom = newBottom; this.rownumber = rownumber; }