Building blocks
Format
A widget is in essence a collection of building blocks strung together. In XML, a building block is the equivalent of an XML element. So the code
<VisualText Text="Hello world"/>
inserts a building block of type 'VisualText' in the Widget Mode representation of the widget. In line with XML specification this code is equivalent to
<?xml version="1.0" standalone="yes" ?> <DrawnXmlWidget PreferredWidgetMode="Block1x1" Name="Hello world" LanguageVersion="1"> <Global></Global> <WidgetMode> <VisualPage> <VisualContent> <VisualText Text="Hello world"/> </VisualContent> </VisualPage> </WidgetMode> <FullScreenMode> <VisualPage> <VisualContent> <VisualText Text="Hello world in full screen!"/> </VisualContent> </VisualPage> </FullScreenMode> </DrawnXmlWidget>
Notice the 'Text' attribute of the VisualText element. Using XML attributes, properties of the building blocks can be set. If an attribute is not explicitely mentionned as an attribute in the XML form, the attribute will have it's default value. All attributes of building blocks are optional, although some will be of little practical use when no attributes are set. Attributes can be of one of the following types:
- string: simply type the value of the property between double quotes, e.g. Name="MyRectangle"
- integer: e.g. Width="50"
- boolean: "true" or "false"
- point: a point is a positional indicator using two integers indicating respectively horizontal and vertical location seperated by a comma, e.g. Location="10,20"
- size: a size is a two-dimensional indicator of size using two integers indicating respectively size in horizontal and vertical direction. E.g. Size="50,50"
- SmartSize: Like the size, but with additional options. The two values in a SmartSize object can be any of the following:
- an integer: just like with a regular size, the size is expressed in pixels.
- the value "Auto": the size will autosize depending on the content.
- a percentage: expresses the size in a percentage of the available size.
- Padding: A padding attribute defines the whitespace inside a container in four directions (left, top, right, bottom). E.g. Padding="0,3,0,3" will set the top and bottom padding to 3 pixels. When the padding in all directions should be the same amount, a single number can be used: e.g. Padding="3".
- color: a color is represented in standard HTML form. A color is preceded with a '#' sign, followed by 3 pairs hexadecimal digits (0-..-9-A-..F). The values of the pairs – ranging from 00 to FF (or from 0 to 255 in decimal form) – represent the values of Red, Green and Blue which constitute the desired color. E.g. TextColor="#FF69B4" will set the color of the text to "Hot Pink".
- Purpose specific enumerations: for some attributes, the list of possible values is a finite list of possibilities. For example, some visual blocks have an attribute ‘Orientation', possible values will be Horizontal and Vertical.
- event: a event property is a special type of property. It's value should be something of type "ActionList". We will handle this later.
- links: widget building blocks can be linked toghether so the output of one block can be transferred as input of another. This will be handled later.
Hierarchy
Building blocks can have a hierarchy. What this means is that a building block can have children building blocks and that a building block can have a parent building block. As we will see later, this is especially important for the building blocks that have a visual component. This parent-child relationship is translated into XML using sub-elements. Examine the XML snippet:
<WidgetMode> <VisualPage> <VisualContent LayoutType="Poster"> <VisualText Text="Hello world!"/> <VisualText Text="This is neat!"/> </VisualContent> </VisualPage> </WidgetMode>
This code snippet should be interpreted as follows: The WidgetMode widget contains an element of type VisualPage. The VisualPage in turn contains a VisualContent block. The VisualContent consists of two VisualText blocks (that are siblings of each other). The result of this code looks something like this:
Types
There are two main type of building blocks : blocks that have a visual representation and blocks that don't. We will call these two type respectively Visual Blocks and Functional Blocks.
Linking building blocks together
From a birds eye perspective, a widget is about gathering information, transforming it, and presenting it to the user. All building blocks perform at least one of these tasks in some way. A block can have multiple inputs and multiple outputs (although only one output per outputtype). Let's say for example you would like to display a list of headlines from slashdot.org. Functionally, you would need to do the following:
- Download the RSS feed of Slashdot.
- Retrieve the titles from the RSS source.
- Display these titles in a list.
The cool thing about widgets is that this translates directly into building blocks:
- Downloading data from the internet -> DataReader block
- Filter the data and keep the relevant parts -> DataFilter block
- Displaying the result of the filter -> VisualDataTemplate block
In our XML format, this looks something like this:
<DataReader Name="source" Url="http://rss.slashdot.org/Slashdot/slashdot"/> <DataFilter Name="filter" Input="source" Filter=".rdf:RDF.item"/> <VisualPage> <VisualHeader> <VisualText Text="Slashdot"/> </VisualHeader> <VisualContent> <VisualDataTemplate Input="filter"> <VisualDataText Filter=".item.title" MultiLine="true"/> <VisualDataSeparator/> </VisualDataTemplate> </VisualContent> </VisualPage>
This is all that is needed to construct a simple RSS reader. Lets look a bit closer at the links between the highlighted blocks. The shaded parts are the necessary plumbing to set up a visual frame.
In this widget, a DataReader block is the source of our information flow. The Url attribute tells it where to get it's information. The DataReader outputs a Data typed object containing the downloaded document in a structured form. We would like to get this data to the DataFilter block to analyze it. This is done using the Name of the DataReader block. Every Building Block has a Name property. The Names can be used to link blocks together. In this case, the DataFilter has an Input property, that is of type Data, which means it takes as value any building block that outputs a Data typed object. Our DataReader named "source" outputs a data object, so it can be used as input for the DataFilter.
The DataFilter block in turn, also outputs a Data typed object, namely a list of matches it found on the input, using the Filter property as filter.
The visual block "VisualDataTemplate" has an input property that is of type Data, so we can link it to the DataFilter block.
This all sounds rather complicated, but when viewed in schematic form, it suddenly becomes natural:
By the way, in result of this widget looks something like this:
On a sidenote: a block can have multiple inputs, but only one output per outputtype. The output of one block can be use as input for multiple blocks.
