All content of a PrintDocument is represented by render objects. A rich hierarchy of render objects is provided by the RenderObject class to represent different types of content.
The table below provides a hierarchy of render object types, with a brief description for each class (note that italics indicate abstract classes):
Render Object Type | Description |
RenderObject | The base class for all render objects. |
RenderArea | Represents a general-purpose container for render objects. |
RenderToc | Represents a table of contents. |
RenderC1Printable | Represents an external object that can be seamlessly rendered in a C1PrintDocument. (The object must support the IC1Printable interface.) |
RenderEmpty | Represents an empty object. Provides a convenient placeholder for things like page breaks and so on where no content needs to be rendered. |
RenderGraphics | Represents a drawing on the .NET Graphics object. |
RenderImage | Represents an image. |
RenderInputBase | The abstract base class for all Preview Forms' input controls. Derived types represent active UI elements embedded in the document when the document is shown by the preview. |
RenderInputButtonBase | The abstract base class for button-like input controls (button, check box, radio button). |
RenderInputButton | Represents a push button. |
RenderInputCheckBox | Represents a checkbox. |
RenderInputRadioButton | Represents a radio button. |
RenderInputComboBox | Represents a combo box (text input control with a dropdown list). |
RenderInputText | Represents a textbox control. |
RenderRichText | Represents RTF text. |
RenderShapeBase | The abstract base class for classes representing shapes (lines, polygons and so on). |
RenderLineBase | The abstract base class for lines and polygons. |
RenderLine | Represents a line. |
RenderPolygon | Represents a closed or open polygon. |
RenderRectangle | Represents a rectangle. |
RenderEllipse | Represents an ellipse. |
RenderRoundRectangle | Represents a rectangle with rounded corners. |
RenderTable | Represents a table. |
RenderTextBase | The abstract base class for classes representing text and paragraph objects. |
RenderParagraph | Represents a paragraph (a run of text fragments in different styles, and inline images). |
RenderTocItem | Represents an entry in the table of contents (RenderToc). |
RenderText | Represents a piece of text rendered using a single style. |
RenderBarCode | Represents a barcode. |
The visible content of a PrintDocument is represented by a tree of render objects with the root of the tree being the Body of the document. You can add a render object to the Children collection of the document's Body, or to the Children collection of another object already in the hierarchy.
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText(); rt.Text = "This is a text."; doc.Body.Children.Add(rt); |
So, the document's Body.Children collection contains all high-level render objects of the document. Moreover, each render object has a Children collection, which contains render objects within it, and so on. (This is quite similar to the Windows Forms' controls that can be nested inside each other. Any control has the collection of contained controls, and so on.)
In addition to the document's body, there are two other regions where you can add render objects in a document, the page header and footer, which are accessible via the PageHeader and PageFooter properties.
Although any render object can contain other render objects as its children, there is one render object designed specifically as a container for other objects, called the RenderArea. The primary difference between a render area and other render objects (such a render text) is that for a render area, specifying either of its width or height as Auto means that the corresponding dimension is determined by the size of the children, while for other types of objects, auto size is determined by the object's own content (text size for a RenderText, image size for a RenderImage, and so on).
By default, when a new render area is created, its Width is equal to the width of its parent (so a top-level render area stretches across the whole page - or across the current column for multi-column layouts). The Height of a render area, on the other hand, is by default set to Auto (Unit.Auto), and is determined by the combined height of the render area's children. So the default behavior of a top-level render area is to take up the whole page width, and stretch down as needed (possibly spanning multiple pages) to accommodate all its content. You can set the Width of a render area to auto (Unit.Auto), in which case it will adjust to accommodate the combined widths of the area's children. In this case, if the combined width of the area's children exceeds the width of the page, horizontal page breaks will occur, adding extension pages to the right of the current page. To prevent horizontal page breaks (clipping the area on the right if necessary), set the area's CanSplitHorz property to False (it is True by default).
Within the parent object or document body (that is, the containers), render objects are by default placed according to the stacking rules, determined by the value of the Stacking property of the container (document for top-level objects), which can be one of the following StackingRulesEnum enumeration members:
Members | Description |
BlockTopToBottom | Objects are placed one beneath the other within the container. When the bottom edge of the current page is reached, a new page is added. This is the default option. |
BlockLeftToRight | Objects are placed one next to the other, from left to right. When the right edge of the current page is reached, a new "horizontal" page is added (a horizontal page logically extends the preceding page to the right; C1PreviewPane shows such pages arranged in a row). |
InlineLeftToRight | Objects are placed inline, one next to the other, from left to right. When the right edge of the current page is reached, the sequence wraps to the next line. A new page is added when the bottom of the current page is reached. |
Stacking rules do not propagate down into the contained objects (children). In other words, if you define a render area and set its stacking to the (non-default) value BlockLeftToRight, and then add another render area inside the first one - its stacking will be the default (BlockTopToBottom) unless you explicitly change it.
You may also use the X and Y properties of a render object to set its position explicitly, which is covered in the next section. Note that in such cases, the render object does not participate in the stacking order at all, so that its position neither affects the positioning of its siblings nor is affected by their positions.
The size and location of a render object are controlled significantly by four properties enumerated below:
All these properties have the value type C1.C1Preview.Unit. The default value for X and Y is Auto (represented by the static field Unit.Auto), which means that the object is positioned according to the stacking rules provided by its parent.
The following table lists the default sizes (width and height) for all render objects, as well as the rules used to calculate auto sizes:
Render objects | Width | Height | Auto Size |
---|---|---|---|
RenderArea | Parent width | Auto | Determined by the combined size of the children. |
RenderToc | Parent width | Auto | Determined by the combined size of the children. |
RenderReport | Parent width | Auto | Determined by the combined size of the children. |
RenderSection | Parent width | Auto | Determined by the combined size of the children. |
RenderC1Printable | Parent width | Auto | Determined by the combined size of the children. |
RenderEmpty | Auto | Auto | 0 |
RenderGraphics | Auto | Auto | Determined by the size of the content. |
RenderImage | Auto | Auto | Determined by the size of the image. |
RenderInputButton | Auto | Auto | Determined by the size of the content. |
RenderInputCheckBox | Auto | Auto | Determined by the size of the content. |
RenderInputRadioButton | Auto | Auto | Determined by the size of the content. |
RenderInputComboBox | Auto | Auto | Determined by the size of the content. |
RenderInputText | Auto | Auto | Determined by the size of the content. |
RenderRichText | Parent width (auto width is not supported). | Auto (determined by the text size). | -- |
RenderLine | Auto | Auto | Determined by the size of the shape. |
RenderEllipse | Auto | Auto | Determined by the size of the shape. |
RenderPie | Auto | Auto | Determined by the size of the shape. |
RenderRoundRectangle | Auto | Auto | Determined by the size of the shape. |
RenderPolygon | Auto | Auto | Determined by the size of the shape. |
RenderArc | Auto | Auto | Determined by the size of the shape. |
RenderRectangle | Auto | Auto | Determined by the size of the shape. |
RenderTable | Parent width (auto width is calculated as the sum of columns' widths). | Auto | Determined by the total width of all columns for width, and by the total height of all rows for height |
RenderParagraph | Parent width | Auto | Determined by the size of the text |
RenderText | Parent width | Auto | Determined by the size of the text |
RenderTocItem | Parent width | Auto | Determined by the size of the text |
RenderField | Parent width | Auto | Determined by the size of the content |
RenderBarCode | Auto | Auto | Determined by the size of the content |
You can override the default values for any of those properties with custom values, and specifying anything but Auto as the value for X or Y coordinates excludes the object from the stacking flow. The size and location properties can be set as absolute values, percentage of parent's size, functions ( such as Min and Max).
Below are some scenarios showing the use of relative positioning of objects to arrange an image and a text.
Place text below image
Let's say you want to place the text below the image simply adding one object after the other to the regular block flow. For such a case, the code snippet is depicted below:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); ra.Children.Add(ri); ra.Children.Add(rt); doc.Body.Children.Add(ra); |
Again, let's say you want to place the text below the image while the children are added to the area in inverse order. The code snippet below depicts this:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); // place image at the top of the parent: ri.Y = 0; // place text below next sibling: rt.Y = "next.bottom"; // auto-size text width: rt.Width = Unit.Auto; ra.Children.Add(rt); ra.Children.Add(ri); doc.Body.Children.Add(ra); |
Place text to the right of image
Let's say you want to insert the image into the regular block flow, while putting the text to the right of the image, centering it vertically relative to the image. For such a case, the code snippet is depicted below:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); ra.Children.Add(ri); rt.Width = Unit.Auto; // add text after the image: ra.Children.Add(rt); rt.X = "prev.right"; rt.Y = "prev.height/2-self.height/2"; doc.Body.Children.Add(ra); |
Also, if you want to place the text to the right of the image, centered vertically, but use the RenderObject.Name in the positioning expressions rather than the relative id "prev", shift the text 2mm towards the right, demonstrating the use of absolute lengths in expressions, the following code snippet can be used.
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); ri.Name = "myImage"; rt.Width = "auto"; rt.X = "myImage.right+2mm"; rt.Y = "myImage.height/2-self.height/2"; ra.Children.Add(ri); ra.Children.Add(rt); doc.Body.Children.Add(ra); |
Now, let's say you want to shift the text to the right at least 6cm, using the built-in Max functions. The code snippet below depicts this:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); ri.Name = "myImage"; rt.Width = "auto"; rt.X = "Max(myImage.right+2mm,6cm)"; rt.Y = "myImage.height/2-self.height/2"; ra.Children.Add(ri); ra.Children.Add(rt); doc.Body.Children.Add(ra); |
Align image to the right of page
Let's say you want to align an image to the right side of the page (utilizing the default value for the width of a render area - parent width), while the text is left-aligned, and centered vertically relative to the image. For this, refer the code snippet below.
C# |
Copy Code
|
---|---|
C1PrintDocument doc = new C1PrintDocument(); RenderText rt = new RenderText("test"); RenderImage ri = new RenderImage(myImage); RenderArea ra = new RenderArea(); ri.Name = "myImage"; // right-align image: ri.X = "parent.right-width"; // left-align text: rt.X = "0"; rt.Y = "myImage.height/2-height/2"; ra.Children.Add(ri); ra.Children.Add(rt); doc.Body.Children.Add(ra); |
PrintDocument provides support for shadows cast by render objects. For this, the API provides the IShadow interface. By default, the shadow is invisible due to being 100% transparent. To show the shadow. transparency value needs to be set less than 100. Other properties can be adjusted as needed.
The IShadow interface includes the following sub-properties:
Render objects | Width | Height | Auto Size |
---|---|---|---|
RenderArea | Parent width | Auto | Determined by the combined size of the children. |
RenderToc | Parent width | Auto | Determined by the combined size of the children. |
RenderC1Printable | Parent width | Auto | Determined by the combined size of the children. |
RenderEmpty | Auto | Auto | 0 |
RenderGraphics | Auto | Auto | Determined by the size of the content. |
RenderImage | Auto | Auto | Determined by the size of the image. |
RenderInputButton | Auto | Auto | Determined by the size of the content. |
RenderInputCheckBox | Auto | Auto | Determined by the size of the content. |
RenderInputRadioButton | Auto | Auto | Determined by the size of the content. |
RenderInputComboBox | Auto | Auto | Determined by the size of the content. |
RenderInputText | Auto | Auto | Determined by the size of the content. |
RenderRichText | Parent width (auto width is not supported). | Auto (determined by the text size). | -- |
RenderLine | Auto | Auto | Determined by the size of the shape. |
RenderEllipse | Auto | Auto | Determined by the size of the shape. |
RenderPie | Auto | Auto | Determined by the size of the shape. |
RenderRoundRectangle | Auto | Auto | Determined by the size of the shape. |
RenderPolygon | Auto | Auto | Determined by the size of the shape. |
RenderArc | Auto | Auto | Determined by the size of the shape. |
RenderRectangle | Auto | Auto | Determined by the size of the shape. |
RenderTable | Parent width (auto width is calculated as the sum of columns' widths). | Auto | Determined by the total width of all columns for width, and by the total height of all rows for height |
RenderParagraph | Parent width | Auto | Determined by the size of the text |
RenderText | Parent width | Auto | Determined by the size of the text |
RenderTocItem | Parent width | Auto | Determined by the size of the text |
RenderBarCode | Auto | Auto | Determined by the size of the content |
The following sample code defines a shadow on a render object:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = c1PrintDocument1; RenderText rt = new RenderText("Sample Shadow"); rt.Width = Unit.Auto; rt.Style.Shadow.Transparency = 20; rt.Style.Shadow.Color = Color.BurlyWood; doc.Body.Children.Add(rt); |
Note that while you do not need to create a Shadow object when setting shadow properties, you may choose to do so, for example, like this:
C# |
Copy Code
|
---|---|
C1PrintDocument doc = c1PrintDocument1; RenderText rt = new RenderText("Sample Shadow"); rt.Width = Unit.Auto; rt.Style.Shadow = new Shadow(20, 100, "1mm", 45, Color.CadetBlue); doc.Body.Children.Add(rt);. |
Borders can be centered over an object's bounds, without affecting either the object's size or the surrounding objects' positions. The BordersModeEdnum specifies the various modes of accounting for border thickness when laying out the objects in a document.
The BordersModeEnum provides the following options: