Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Understanding Styles

4.7

Styles are everywhere in a Scryber document. They affect the appearance and behaviour of all the components.

How styles work

Styles work in a similar way to cascading stylesheets in html documents, and if you are familiar with CSS, you should be able grasp the concepts behind Scryber styles very quickly.

All styling information is contained in a style definition (Scryber.Styles.PDFStyleDefn).
You can define styles either on the visual component itself, at the top document level, or in an externally referenced style sheet.

A style definition contains one or more Style items which in-turn contains one or more Style values.

They are build up into a complete definition of how a component should be represented.

To see each of the style options and their attributes go to Out of the box style items

Inline styles

The easiest way to define styles is inline with the component. Most of the common features of styles are available inline, and are convenience properties onto the underlying style definition of the visual component.

<pdf:Page styles:bg-image="../images/pagebg.png" styles:bg-repeat="RepeatX" >
<Content>this is the content of the page</Content>
</pdf:Page>

Here we have a page with a background image that will only repeat over the horizontal direction. We could do the same with the code.

	 PDFDocument doc = new PDFDocument();
	 PDFPage pg = new PDFPage();
	 pg.BackgroundImage = Server.MapPath("../images/pagebg.png");
	 pg.BackgroundRepeat = Scryber.PatternRepeat.RepeatX;
	 doc.Pages.Add(pg);
	

If we look at the PDFVisualComponent class we can see the convenience properties.

        #region public string BackgroundImage

        /// <summary>
        /// Gets or sets the background image of this component
        /// </summary>
        [PDFAttribute("bg-image", Const.PDFStylesNamespace)]
        public string BackgroundImage
        {
            get
            {
                PDFBackgroundStyle bg;
                if (this.HasStyle && this.Style.TryGetBackground(out bg))
                    return bg.ImageSource;
                else
                    return string.Empty;
            }
            set
            {
                this.Style.Background.ImageSource = value;
            }
        }

        #endregion	
	

This shows the getter looking for the PDFBackgroundStyle style item and the setter explicitly setting the value in the Style.Background property path.

NOTE: When using paths to resources in Scryber documents, they can only be relative if the document is loaded from a path itself. If the document is dynamically created then the path to component resources must be absolute, or the LoadedSource needs to be set to a full path where reference paths are relative to.

An Example of Inline Styles

Inner Style Element

Again within the PDFVisualComponent class we can see the Style read-only property. This property will never return a null reference, but will be instantiated if accessed. It is this property that the BackgroundImage property is using for defining the image source on a background style item.

        /// <summary>
        /// Gets the applied style for this page Component
        /// </summary>
        [PDFElement("Style")]
        public PDFStyle Style
        {
            get 
            {
                if (_style == null)
                    _style = new PDFStyle();
                return _style; 
            }
        }
	

As it is declared with a PDFElementAttribute, the XMLParser knows that there can be an inner ‘Style’ element on any visual component. This means that properties not available on the convenience methods are still available to be declared on the component itself.

	  <pdf:Page styles:bg-image="../images/pagebg.png" styles:bg-repeat="RepeatX" >
	    <Style >
	      <styles:Background y-pos="100pt" x-size="200pt" x-step="230pt" />
	    </Style>
	    <Content>this is the content of the page</Content>
	  </pdf:Page>
	

So above we can see that the background image, now has a vertical offset of 100pt’s and a specific width and step. These properties are only available on the PDFBackgroundStyle class, and not pushed up onto the component.

We can also use them in the code.

        PDFDocument doc = new PDFDocument();
        PDFPage pg = new PDFPage();
        pg.BackgroundImage = Server.MapPath("../images/pagebg.png");
        pg.BackgroundRepeat = Scryber.PatternRepeat.RepeatX;
        //Add the background step properties.
        pg.Style.Background.PatternYPosition = 100;
        pg.Style.Background.PatternXSize = 200;
        pg.Style.Background.PatternXStep = 230;
        doc.Pages.Add(pg);
	

NOTE: The parser reads attributes and then inner elements. Therefore if there are duplicated values inline and within the child element, then the child element will override.

An Example of Inner Element Styles

Why choose inner elements over inline attributes?

The inner elements are much more verbose. They take longer to write and are harder to read, so why use them at all?

The inner style is a collection of Style Items. This collection is not limited to the styles defined, but can be extended so that any parsed class instance can be defined. Therefore the inner element is not limited to only styles that it knows about, and new styles can be created, defined in the XML and carried through the full style generation process until another component that knows about this style item can use it. 

Out of line Style Definitions

Defining styles on the component is fine for simple documents, but as things get more complex it is easier to define styles away from the component itself and include a reference to that style so that it is automatically applied.

Style definitions are added to the top of a document either as a full definition, or a reference to an external style sheet.

	<pdf:Document xmlns:pdf="...."
	                         xmlns:styles="....">
	  <Styles>
	    <!-- External stylesheet -->
	    <styles:Styles-Ref source="../styles/MyStylesheet.psfx"/>

	    <!-- Style definition -->
	    <styles:Style applied-type="pdf:H1">
	      <styles:Fill color="blue" />
	      <styles:Font family="Bauhaus 93" size="60pt" />
	    </styles:Style>

	  </Styles>
	  <Pages> 
	     <!-- Document content. -->
	  </Pages>
	</pdf:Document>
	

We could also define in the code in a similar way.

        PDFDocument doc = new PDFDocument();
        Scryber.Styles.PDFStyleRef sref = new Scryber.Styles.PDFStyleRef();
        sref.Source = Server.MapPath("../styles/MyStylesheet.psfx");
        doc.Styles.Add(sref);

        Scryber.Styles.PDFStyleDefn defn = new Scryber.Styles.PDFStyleDefn();
        defn.AppliedType = typeof(Scryber.Components.PDFHead1);
        defn.Fill.Color = Scryber.Drawing.PDFColors.Blue;
        defn.Font.FontFamily = "Bauhaus 93";
        defn.Font.FontSize = 60;
        doc.Styles.Add(defn);
	

An external stylesheet (by convention .psfx) is simply a bunch of style definitions, or a bunch of references to other external stylesheets (or a combination of both).

So within MyStylesheet.psfx we could define the page type style. All documents that then referenced this stylesheet would then have A4 pages with the background, unless this was overridden in later styles or explicitly on pages.

	<style:Styles xmlns:pdf="...."
	         xmlns:style="...." >

	   <style:Style applied-type="pdf:Page" >
	   <style:Padding top="10pt"/>
	   <style:Margins all="10pt" />
	   <style:Border color="black" width="0.2"/>
	   <style:Font size="12pt" family="Times" />
	   <style:Page size="A4"/>
	   <style:Background img-src="../images/pagebg.png" repeat="RepeatX" y-pos="100pt" x-size="200pt" x-step="230pt" />
	</style:Style>

	<!-- more styles or references -->
	</style:Styles>
	

There are 3 options or combination of options for a style to be applied - applied-type, applied-class, applied-id

If more than one is declared on the style, then they must all match in order for the style to be applied. If one of them does not match then none of the Style Items would be applied to the component in question.

An example of out of line styles

Applied type

The applied type for a style refers to the actual runtime type of a component. On the style instance this is declared as a System.Type value. e.g.

	 Scryber.Styles.PDFStyleDefn defn = new Scryber.Styles.PDFStyleDefn();
	 defn.AppliedType = typeof(Scryber.Components.PDFPage);
	

In the xml document, the Scryber Xml parser must be able to uniquely identify the type (using the same mechanism as when loading components - see XmlParser). This declaration this can be any value that can resolve into a parsable component using the name and namespace prefix. e.g.

	 <style:Style applied-type="pdf:Page" >
	

When the style is being checked for applicability to the current component, then if there is an AppliedType value, the current component must be able to be cast as that type.
If a component is of a class that inherits from the specified type, then it is considered applicable. For example the PDFSection class inherits from PDFPage. All styles which are applied to type page will also be applied to sections, but styles which are applied to sections will not be applied to pages.

Applied Class

The applied-class attribute is simply a key name. It is matched against the style:class (component.StyleClass) value of the component. It is case sensitive.
No type checking is done, so the style can be applied to any type of component (not all components respond to all style items).

	<pdf:Document xmlns:pdf="...."
	                         xmlns:styles="....">
	  <Styles>

	    <styles:Style applied-class="bluebg" >
	      <styles:Background color="blue" />
	      <styles:Fill color="white"/>
	    </styles:Style>

	  </Styles>
	  <Pages>

	    <pdf:Page id="titlepage" styles:class="bluebg" >
	      <Content>Just some white text on a blue bg</Content>
	    </pdf:Page>

	    <pdf:Page id="innercontent" >
	      <Content>
	        <pdf:Div styles:class="bluebg" >
	          Just some white text on a blue bg
	        </pdf:Div>
	      </Content>
	    </pdf:Page>
	  </Pages>
	</pdf:Document>
	

This can also be defined almost as simply in code.

        PDFDocument doc = new PDFDocument();

        Scryber.Styles.PDFStyleDefn defn = new Scryber.Styles.PDFStyleDefn();
        defn.AppliedClass = "bluebg";
        defn.Background.Color = Scryber.Drawing.PDFColors.Blue;
        defn.Fill.Color = Scryber.Drawing.PDFColors.White;
        doc.Styles.Add(defn);

        PDFPage pg = new PDFPage();
        pg.StyleClass = "bluebg";
        pg.Contents.Add(new PDFTextLiteral("Just some white text on a blue background"));

        PDFPage pg2 = new PDFPage();
        PDFDiv div = new PDFDiv();
        pg2.Contents.Add(div);
        div.StyleClass = "bluebg";
        div.Contents.Add(new PDFTextLiteral("Just some white text on a blue background"));

        doc.Pages.Add(pg);
        doc.Pages.Add(pg2);
	

In both cases the page and div with a style-class of bluebg will have a white text on a blue background. In the case of the first page, it will be completely blue. For the div it will be the full width, but only the height of the text.

Applied id

The applied-id is the most specific of the style applications. Component id’s should be unique for each file / template so the style will only be applied to items with the id - case sensitive.

	<pdf:Document xmlns:pdf="...."
	              xmlns:styles="...."
	              xmlns:data="....">
	  <Styles>

	    <styles:Style applied-id="titlepage" >
	      <styles:Margins all="100mm" />
	      <styles:Fill color="#FF0000"/>
	      <styles:Position h-align="Center"/>
	    </styles:Style>

	  </Styles>
	  <Pages>

	    <pdf:Page id="titlepage" >
	      <Content>Just some red text in the middle of the page</Content>
	    </pdf:Page>

	  </Pages>
	</pdf:Document>
	

Or in code

        PDFDocument doc = new PDFDocument();

        Scryber.Styles.PDFStyleDefn defn = new Scryber.Styles.PDFStyleDefn();
        defn.AppliedID = "titlepage";
        defn.Margins.All = new Scryber.Drawing.PDFUnit(100, Scryber.Drawing.PageUnits.Millimeters);
        defn.Fill.Color = new Scryber.Drawing.PDFColor(1, 0, 0);
        defn.Position.HAlign = Scryber.HorizontalAlignment.Center;
        doc.Styles.Add(defn);

        PDFPage pg = new PDFPage();
        pg.ID = "titlepage";
        pg.Contents.Add(new PDFTextLiteral("Just some red text in the middle of the page"));

        doc.Pages.Add(pg);
	

Combining Styles

All 3 style application types can be combined in a definition for increased identification of required components. An applied-type of pdf:Label and applied-class of "emphasis" would only be applied to PDFLabel instances with a StyleClass value of "emphasis".

	<styles:Style applied-type="pdf:Label" >
	  <styles:Font family="Helvetica" size="12pt" bold="false" italic="false" />
	</styles:Style>

	<styles:Style applied-type="pdf:Label" applied-class="emphasis" >
	  <styles:Font size="14pt" bold="true" />
	  <styles:Fill color="red"/>
	</styles:Style>
	

In this case all the labels will be regular 12pt Helvetica. Labels with an "emphasis" class will be 14pt bold in red. If we change the font-family of labels to Times or Comic strip then this will be applicable to both, but a div with style-class of emphasis will not get any of these styles.

Multiple Styles

All components support the application of multiple style classes on the style:class attribute. Each applied class name must be separated with a space (and this also means that all applied class names must not contain a space, or they will never get applied).

When multiple styles are defined they are applied in the same order as written. For example if a component has a style class of ‘bordered bluestroke’ then the bordered style items would first be applied and then the bluestroke style items would be applied, finally building the full style.

Databinding Styles

As the components have style values associated with them directly the attributes of each style can be bound to a source value. As with all binding the string result of the xpath expression must be convertible to the the required type.

 

You can find more information on each of the style items and their available values in Out of the box Style Items



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  4.7   
00012
12345
Number of Ratings : 3
  Comments
Add Comment
No Comments Yet