REBOL Forces Return to Old Documentation Archive

 

REBOL

 Internet Communications LanguageTM

REBOL/View User's Guide

Version 0.9.9 (Beta 4.1)
1-June-2000


Refer to the REBOL/Core User's Guide for information on additional functions.  

Contents

Introduction

Basic Definitions
Brief Examples

Visual Interface Dialect (VID)

Creating Face Layouts
Displaying Faces
Using VID
Styles

Face Details

Positions and Sizes
Face Feelings
Edge Facet
Font Facet
Paragraph Facet
Feel Facet
Effect Properties

Events

Handling Events
Understanding the Feel Facet
The Event Mechanism

Features

Iterated Faces
Virtual Coordinates Space (not working in Beta 4)

Datatypes

pair!
image!
event!

Parsing Blocks and Dialects

Dialect Examples
Block Operations
Parsing Sub-blocks

Feedback


Introduction

REBOL/View provides a powerful method of creating interfaces with a two-dimensional graphical compositing system. Although this system is useful for implementing various graphical-user-interface (GUI) designs, it remains straightforward when compared with traditional approaches. In addition, REBOL/View is highly portable and will be released on numerous platforms.

In REBOL, there are two ways to build graphical interfaces. The easiest way is to use a dialect that accepts simple descriptions and converts them to their underlying graphical objects. The other way is to define the necessary graphical objects directly. Both have advantages. For most applications, using a dialect produces the most results with the least effort. However, some special interfaces and behaviors can only be created by directly specifying the objects.

For instance, using a graphical interface dialect such as VID (Visual Interface Dialect), specify a window using a higher level description such as:

backdrop %mountains.jpg
title "Image File Viewer"
across
button "First" [list: head list]
button "Next"  [list: next list]
button "Back"  [list: back list]
button "Last"  [list: back tail list]

Note that this is REBOL code; actually a dialect of REBOL. VID is an integrated part of  REBOL/View.

There can be many such dialects. For instance, dialects are designed depending on the purpose of the interface, such as the folder/icon framework of a computer desktop, the scene orientation of a TV set-top box, the slide transition model of a presentation engine, the touch screen of a kiosk, the playfield style of a video game, or the restricted display area of a handheld device.

The ability for such dialects to allow a simple, flexible, and incremental description of content is the same characteristic that allowed HTML to become rapidly accepted by users. In such dialects there are defaults for everything. A user can easily extend and enhance the display, and almost any description can render a display, even if it is not precisely what the user expected.

Getting back to VID. It makes it possible to describe styles such as buttons, text boxes, sliders, fields, text areas, and more. By contrast, the fundamental graphical objects of REBOL do not allow for this level of control. Instead, they specify the attributes of an area of the screen such as its color, image, position, size, feel (mouse events), etc.

For instance, making an object directly with a simple image can be shown with the code:I

image-face: make face [
    offset:  0x0
    size:    1000x1000
    image:   load %backdrop.jpg
    effect:  'fit
    edge:    none
]

This requires much more detail for each display object when compared to the dialect. However, it provides a greater degree of control over the attributes of each of these objects. The display objects provide the powerful building blocks upon which a wide range of graphical metaphors can be built. Each interface consists of a tree of graphical objects that describe the content and attributes of their spatial areas.

Definitions

There is only one type of graphical display object in REBOL. It is called a face. Faces are graphical areas. A typical user interface is constructed from a number of such faces, each of which may provide a different look and feel depending on its attributes.

The attributes of a face are called facets. They include location, size, color, image, font, style, paragraph format, rendering effects, feeling, and other information. Some of the more detailed facets, such as fonts, edges, and paragraph attributes, are objects themselves. This allows the reuse of specific object characteristics by sharing them between many display objects. For example, a group of buttons often use the same edge, font and paragraph attributes. As a result, a natural object-oriented method of specification simplifies new display object specification.

A face may contain other faces. It can be a single face or a group of faces. A face or group of faces contained inside another face is called a pane. When a face contains a pane it becomes a parent face. Panes are repositioned simply by changing the position of the parent. Within a pane, faces are drawn in the order in which they are encountered. Panes may be placed inside of panes creating a tree of graphical objects. Each pane is positioned relative to its parent. This is the hierarchy used by the internal composting system.

When the facet attributes of a face are defined, it can be used as a style. A style is a predefined face that is used as a template for creating new faces. Styles are used by VID. Default styles such as titles and buttons are standard in VID. A style may include a hierarchy of panes. Using styles allows content to be created through inheritance, changing only the facets that need to be different. For instance, a series of buttons might be used and all that would change between them is their label and behavior.

A face list can be created through iteration. For instance, when displaying a list of ten buttons, the buttons do not need to be created individually. The buttons may only differ by a few facets, such as the text, position and behavior. A template face can be used in an iterator loop to create each of the faces in the face list. This is useful when creating scrolling lists of files and other data sets that share the same appearance.

Faces are displayed with the view function. There are a variety of ways to create a face to display. For instance, the layout function creates a face by using the Visual Interface Dialect that takes advantage of predefined styles. This is the most convenient approach. A face can also be created directly with the make function.

The following section introduces a few simple examples of using layout and view to display faces.

Brief Examples

The simplest example program is one that displays a single string. To do this, make a face that defines the string to display with layout, then pass that face to the view function. In the REBOL tradition, this takes only one line:

view layout [text "Hello World!"]

The result is a simple view window with "Hello World!" centered in the display:

The layout function utilizes styles. The above window displays the font in white with a slight shadow effect on a medium gray background. Notice that the line of code that produced the window did not define these facets. This is because the font and face attributes were inherited from styles. These styles are already defined in VID. They are stored in the system/view/vid object. The standard VID styles are shown later under Style Keywords.

New styles can be created from existing ones. The examples below demonstrate overriding these default styles.

In this next example, the string is displayed in a yellow font:

view layout [text "Hello World!" 255.255.0]

The result is a window just like the one shown above, but with yellow text:

Any of the properties of a style can be modified. To modify them using VID, follow a style keyword with a defining property. In the above example, the text keyword was followed by a string and an RGB tuple value. The tuple value defined the color of the font as yellow. This created a new face object that inherited the properties of the text style, but changed only the font's color.

There are many styles in VID. The following example uses the title style:

view layout [title "Hello World!"]

This displays the following:

Changing the color of the backdrop can be done with the keyword backdrop:

view layout [backdrop 0.128.0 title "Hello World!"]

This results in displaying the "Hello Sunny World!" text over a medium green background:

Instead of a green background, an image can be used:

view layout [backdrop %carlwaves.jpg title "Hello World!"]

This creates a display with an image stretched to the dimensions of the background:

The view, layout and stylize functions are explained in full in The Visual Interface Dialect.

Visual Interface Dialect (VID)

The Visual Interface Dialect (VID) is designed to simplify the implementation of View scripts using styles. VID consists of a set of functions. These functions handle displaying face layouts and windows and a lot more. They are as follows:

  • stylize - create style sheets
  • layout - creates face structures
  • view - displays View windows
  • unview - closes View windows
  • get-style - returns the face object of a style

The most powerful of these is the layout function, as it uses the actual Visual Interface Dialect to create the face structures. The dialect makes it possible to easily design and program visual interface REBOL/View scripts with extensive functionality. Recall the the "Hello World!" examples illustrated before. Those examples all used the layout function. Note the following example that views a face directly:

view make face [
    size: 100x50
    edge: make edge [size: none]
    pane: make face [
        size: 100x50
        text: "Hello World!"
        font: make font [
            color: 255.255.255
            shadow: 1x1
        ]
        edge: make edge [size: none]
    ]
]

Viewing a face directly means you have to set a lot of the face's facets directly in order to achieve the desired effect. Faces are explained in detail in The Face Object. Using layout, nearly the same as above can be accomplished with:

view layout [text "Hello World!"]

In the above example the face layout is created with layout. Inside the block passed to layout, the text "Hello World!" is defined to the text style. This is part of the Visual Interface Dialect the layout function uses. The layout function is explained in full later.

New styles can be created when a different set of styles other than the defaults are desired. This reduces the need to mess with specifying detailed face definitions. The look and feel of a GUI will normally follow a certain style guideline. Styles can be created to meet the requirements of any style guideline. These styles are assigned to a style sheet. For instance, if a series of buttons are going to be used that will follow a specific guideline, a style sheet can be created for them:

my-styles: stylize [
    ...
    back-button button [ ... ]
    next-button button [ ... ]
    head-button button [ ... ]
    tail-button button [ ... ]
    ...
]

These buttons can be placed in the viewed layout:

view layout [
    my-styles
    ...
    across
    head-button back-button next-button tail-button
    ...
]

Thus far, the layout, view and stylize functions have all been used throughout the examples illustrated above. The following sections describe these functions and how they are used. As well, VID concepts are explored to much greater detail.

Creating Face Layouts

Using the layout function allows intricate face structures to be created quickly and with little code. It handles the creation and placement of buttons, checkboxes, text fields, slider bars and more. Each of these styles are customizable. New styles may be created that will be recognized by layout. These styles may be placed all in the main face, grouped in sub faces or both.

As its argument layout takes a block. This block uses the Visual Interface Dialect. The block is evaluated by layout and a face returned. This face is used by view to display or update a window. VID is discussed in detail in Using VID. The power of layout lies in VID's design.

The layout function supports refinements that are be used to define specific attributes of the top level parent face returned. Because the top level face defines how view will display a window, this control is needed. The refinements are described in the following table:
 
Layout Refinements
/size pair

The size of the top level face. This will force the size of the face the layout is created in. The default is to size dynamically based on the placement of items within the layout.

layout/size [ ... ] 800x600

/offset pair

The offset where the window will be displayed relative to the actual screen space available. This behaves the same as view/offset. The default offset is 20x20:

layout/offset [ ... ] 30x10

This example displays a window with a top left corner 30 pixels in and 10 down
from the top left of the screen.

/style block

A block defining the face attributes of the top level face. Any of the face attributes may be defined:

layout/style [ ... ] [edge: make edge [size: 4x4]]

This example displays the window with the constructed layout set inside a parent face with its border 4 pixels thick and the default color.

/origin pair

Sets the pixel offset to begin lining up items inside the top level face. The default is 20x20, which is to say,  20 pixels of padding:

layout/origin [ ... ] 0x0

The above example starts placing images with no padding.

Displaying Windows

The view function creates and updates windows. It takes a face as its argument. The first use of view within an application is special. It displays the window and initializes the graphical interface system of REBOL. Subsequent calls to view update that window, changing its content to the new face that is supplied. It is designed to make it easy for applications to change the contents of the window. When the face passed to view contains a pane of sub-faces, they will simultaneously be shown.

The first call to the view function will not return immediately. The application code is event driven, calling functions associated with various faces. While the first call to view remains active, all other calls to view will return immediately. The first call will return only after all windows have been closed or if the /new refinement is used. In all cases, when view does return, it returns the face object it displayed.

Additionally, calls to view can specify refinements for offset, options, and title. These will impact the attributes for new and updated windows. If these refinements are not provided, defaults will be used. The default offset is 20x20. The window has borders and is resizable. And, the window title is the script header title string.
 
View Refinements
/offset pair

The offset where the window will be displayed relative to the actual screen space available:

view/offset face 0x0

The example display a window with a top left corner fit against the top left edge of the screen.

/options word
block
Behavioral options that control how the window behaves. See options in the Face Object Definition table below for further information.
/title string

The title for the opened window.

view/title face "Hello World Example"

/new

Create a new window. Up to eight individual windows can be created. When this refinement is used, the face object for the new window is returned:

window2: view/title/new face "Second Window"

Multiple refinements may be used together to create the desired effect:

view/offset/title face 0x0 "My REBOL!"

Current resolution can be determined by looking at the value of system/view/screen-face/size:

probe system/view/screen-face/size

The unview function closes the last opened window. This function has two refinements, /all and /only. Use the /all refinement to close all open windows. The /only refinement takes a face object as its argument. If that face object exists in the system/view/screen-face/pane block, that window will be closed.

The show function is a native for displaying and redrawing faces. Use show when adding or modifying faces in an existing display. It refreshes that face or any of its parent faces. An error is generated if show is called on a face that is not a main window face or one of its panes. Ideally, show should be used on a pane of the main window face. The difference between show and view is that show is used to refresh any face in a displayed window while view only displays or redraws the window itself.

When you show a face that is a pane and it contains a block of other faces, they are all be rendered together. Individual sub-faces may be rendered selectively by calling show on a block of faces. Every face in the block will be rendered simultaneously. A face may not be displayed if its offset causes it to fall outside of the parent face (gets clipped) or is obscured by another face.

A face is hidden from view with the hide function. This function takes a face or a block of faces as its argument. This removes a single face, an entire pane of faces or a block of faces . Hide the parent object before making major changes to its pane block. This prevents stray user-interface events from interacting with the faces while modifying the pane. To reshow a face that was hidden with hide, use show.

Using VID

VID consists of key words and their properties. Each keyword defines a visual attribute. VID keywords at first look like functions, but they are not. They are keywords that tell the layout function to add an attribute with certain properties. Two such keywords are used in the example below:

view layout [backdrop 10.10.150 text "Hello World!" 255.255.0]

These keywords are backdrop and text. They were used with properties that defined the backdrop and text styles before they were displayed. The above example produces the following window:

There are many predefined styles. For instance, a predefined style called title can be used to render a large font:

view layout [backdrop 10.10.150 title "Hello World!"]

This creates the following display:

The style title is predefined to use a yellow font with a shadow effect and the size of 24.

The backdrop keyword was used with a single property. This was an RGB tuple value that defined the color of the backdrop. An image could be used instead:

view layout [backdrop %bay.jpg title "Hello World!"]

Which manifests the following window:

A lot of control is available over the effects of the attribute keywords used. For instance, to darken the backdrop image so the text is more readable:

view layout [backdrop %bay.jpg 150.150.150 title "Hello World!"]

This manifests the following window:

The tuple value used after the backdrop keyword colorized the bay.jpg image. This is just one brief example of what can be done with VID. A number of keywords are provided that allow for the creation of rich visual interfaces.

The face created by layout is sized dynamically based on the content provided. For instance, if a button is added to the "Hello World!" example above:

view layout [
    backdrop %bay.jpg 150.150.150
    title "Hello World!"
    button "say hi"
]

This raises the following display:

If even more styles are added:

view layout [
    backdrop %bay.jpg 125.125.125
    title "Hello World!"
    text 220 {
        Say hi to the world and all it's minions! Be
        bold and say howdy do! Hi hi hi hi hi!
    }
    across button "say hi" button "say bye"
]

This displays the following window:

Keyword Properties

Each VID keyword is followed by one or more defining properties. VID will use defaults for any properties left undefined. So not all the properties of a keyword need be defined in order to create the desired effect. Some of VID keywords may rely heavily on their defining properties. Properties follow a specific guideline. In most cases a property will behave the same when used with different keywords. For instance, notice how in the last example a string used with styles title, text and button behaved the same for each of them by setting the style's text to that string.

With this in mind, it makes sense to first look at the defining properties of VID's keyword attributes. Following is a list of the keyword properties:
 
VID Keywords Properties
Values Uses
number For defining field widths.
pair For defining an item's size or providing an positioning offset.
string For defining the text used in an item.
tuple For defining the color of  a face or font. When an image has been included among the properties, the tuple will specify the colonization of that image.
file Specifies an image file.
image For placing an image item.
char For defining a shortcut key. When the window is displayed, the shortcut key will evaluate the action property defined for the item.
block For evaluating whenever an action occurs in the item. For instance, when a button item is clicked or a slider bar is dragged.
word

Word properties are used to allow more detailed control over how a property is used by a keyword. Some of the word values take a property value of their own, usually a block:

  • data - Followed by a block of values to be used as data.
  • effect - Followed by a block of effect values. These effects will change the way a face is displayed. Effects are explained under Face Details in the Face Object Definition table.
  • left, right, up, down - Forces the face to force a certain direction.
  • of - Followed by a ticked word ('word). This word causes the placed style to belong to a certain group. For instance, in the case of radio buttons.

These property rules stay consistent wherever they are used within VID.

There are three types of keywords used in VID. The first is a style, the second a position and the third an action. Style keywords place visual elements in the layout and define the look and feel. Position keywords define the current position in the layout where styles will be placed. Action keywords evaluate REBOL code within the layout.

Style Keywords

The style keywords are the most fundamental. This is because they create and modify the visual elements seen in REBOL/View display. For instance, the button keyword will place a button and the backdrop keyword will affect the look of the background.

There are many style keywords to choose from:
 
VID Style Keywords
Keyword Description
size Sets the size of the main window. Takes a pair value. Using this keyword will override the default dynamic size allocation.
space Sets the spacing between all styles following the keyword. Takes a pair or integer value. These represent pixel spacing. If it is a pair, x will represent horizontal spacing while y represents vertical spacing. If it is an integer, both horizontal and vertical spacing will be the same.
backdrop Sets the color or image of the background. When an image is used, it will be stretched to the size of the window. Uses the properties tuple, file, image, char, block and word. The word accepted is effect.
backtile Sets the color or image of the background. When an image is used, it will be tiled throughout the window. Uses the properties tuple, file, image, char, block and word. The word accepted is effect.
image Places an image. Uses the properties pair, string, color, file, image, char, block and word. The word accepted is effect.
title Places a text element. The text is yellow bold with a three pixel drop shadow at size 20. Uses the properties integer, pair, string, tuple, file, image, char, and block.
subtitle Places a text element. The text is yellow italic with a three pixel drop shadow at size 18. Uses the properties integer, pair, string, tuple, file, image, char, and block.
stress Places a text element. The text is white bold italic with a one pixel drop shadow at size 12. Uses the properties integer, pair, string, tuple, file, image, char, and block.
label Places a text element. The text is white with a one pixel drop shadow at size 12. Uses the properties integer, pair, string, tuple, file, image, char, and block.
text Places a text element that will wrap. The font definitions are defined the same as text. When text reaches the specified width of the face, it will word wrap to the next line. Uses the properties integer, pair, string, tuple, file, image, char, and block.
field Places a one line edit field. Uses the properties integer, pair, string, tuple, file, image, char, and block. The block value will be evaluated when the return key is pressed. When a char value is used, that character will not type into the field, instead it will evaluate the block value. If more than one field or area style are used in the layout, pressing tab or return will shift between the editable fields.
area Places a multi-lined edit field. Uses the properties integer, pair, string, tuple, file, image, char, and block. When a char value is used, that character will not type into the field, instead it will evaluate the block value. No default method is used to evaluate the block value.
button Places a button. Uses the properties pair, string, tuple, file, image, char, and block.
arrow Places a button with an arrow in it. Uses the properties pair, tuple, file, image, char, block and word. The words accepted are left, right, up and down. By default, arrow buttons face up.
toggle Places a toggle button. When clicked, it will remain pressed until clicked on again. Uses the properties pair, string, tuple, file, image, char, and block.
rotary Places a rotary button. The button's label changes each time it is clicked. Uses the properties pair, string, tuple, file, image, char, block and word. The word accepted is data.
choice Places a select button. A list of selectable items pops up when the button is pressed. Uses the properties pair, string, tuple, file, image, char, block and word. The word accepted is data.
check Places a check box. Clicking toggles an 'x' within the box. Uses the properties pair, tuple, file, image and char.
radio Places a radio button. Multiple radio buttons may be classed as part of the same group. Uses the properties pair, char and word. The word accepted is of.
slider Places a slider bar. The slider bar can be implemented to control effects in other faces or windows. Uses the properties pair, string, tuple, file, image, char, and block. Moving the slider bar will evaluate the block value. The data facet in the face represented by the slider style is updated with a numeric value when the slider bar is moved. This is a pixel value between 0 and the length of the bar.
progress Places a progress bar. The progress bar can be implemented to show the progress of renderings, downloads, copies and more. Uses the properties integer, pair, string, tuple, file, image, char, block and word. The integer value will represent the percentage of 'progress' to show on the bar. These value will be between 0 and 100. The accepted word value is effect.
box Places a box. This can be used as a spacer or for creating special effects. Uses the properties pair, string, color, file, image, char, block and word. The word accepted is effect.
frame Places a box with an ibeveled edge. This frame can house an image or produce specialized effects. Uses the properties pair, string, color, file, image, and word. The word accepted is effect.
sensor An invisible area of the screen that can detect events. Uses the properties pair, tuple, file, image, char, and block.
panel Places a panel. This panel is a sub layout and takes a layout block that uses VID. Uses the pair value.
list Places a list. A list is an iterated sub layout and takes a layout block that uses VID. The styles in the layout will be repeated downward until there is no more room to fit them within the list dimensions.

Positional Keywords

Positional keywords control where styles are placed in the layout. There are several positional keywords. These are origin, across, below, return, guide, indent, tab, tabs, pad and at. They are used to place styles in specific locations and orders. The way these keywords are used is explained individually with examples below.

Origin

The origin keyword is used once to set the origin within the layout where styles will begin placement. It takes a pair value that determines how close to the window border to begin placing styles. Padding of the same distance will be created at the bottom and right edges of the window. The padding is created between the bottom most and right most styles within the layout.  If no value is given, it then will return the origin position which can be set to a word. The default is origin is 20x20.

The following example will start placing styles at 5 pixels from the left edge and 10 pixels down:

view layout [
    origin 5x10
    ...
]

Across and Below

The across and below keywords control which direction styles will be placed. This is either horizontally or vertical, respectively. The default is below. For instance, if three buttons are placed in the layout:

view layout [button "one" button "two" button "three"]

This displays three buttons in vertical order:

When the across keyword is used:

view layout [across button "one" button "two" button "three"]

Now the three buttons are displayed in horizontal order:

When one of these keywords is used, styles are placed in that direction until another positional keyword changes this. For instance, the following example uses three more buttons, "four", "five" and "six". The first three are displayed horizontally and the last three vertically:

view layout [
    across
    button "one" button "two"  button "three"
    below
    button "four" button" five" button "six"
]

This creates the following window:

Return

The return keyword starts the placement of styles in the next virtual column or row. It can be thought of as a virtual row when the across keyword is being used and a column when using below. For example, the six buttons in the above example can be neatly rearranged. Using the return keyword before placing the last three buttons will cause them to appear in a new column to the right of the first three. Because the below, or column effect is default, the below keyword does not need to be used:

view layout [
    button "one"  button "two"  button "three" return
    button "four" button" five" button "six"
]

This displays two columns of buttons. The first column contains the buttons "one", "two" and "three". In the second column the buttons "three", "four" and "five" appear:

 

Using return with the across keyword will create two rows instead of columns:

view layout [
    across
    button "one"  button "two"  button "three" return
    button "four" button" five" button "six"
]

The above example displays the following. Now "one", "two" and "three" are displayed horizontally along the top while "four", "five" and "six" are beneath them:

Guide

The guide keyword sets a sort of virtual guideline. For instance, when the return keyword is used to start a new column or row, it will start at the set guideline instead of the top or left of the window. In the following example, a title is placed above three columns of two buttons:

view layout [
    title "Six Buttons"
    button "one"   button "two"  return
    button "three" button "four" return
    button" five" button "six"
]

This creates a rather undesired effect:

The return keyword started a new column relative to the title text. Using the guide keyword makes it possible to start a new column relative to the first placed button. The following example is the same as the one used above, except guide is used to set a new virtual column below the title text:

view layout [
    title "Six Buttons"
    guide
    button "one"   button "two"  return
    button "three" button "four" return
    button" five" button "six"
]

This creates a more appropriate display:

This same rule applies to horizontal placement with across. The guide keyword also accepts a pair value as a defining property. This pair value defines where to place current virtual grid. For example, this next example starts the grid at 150x150 pixels. Face positions and sizes is covered in detail in the next section under Positions and Sizes. For now, settle with the fact that this is basically 150 pixels in and down from the left top edge:

view layout [
    title "Six Buttons"
    guide 150x150
    button "one"   button "two"  return
    button "three" button "four" return
    button" five" button "six"
]

This manifests a display where the three columns of buttons start at the location specified. The effect becomes fairly clear when seen:

Indent

The indent keyword creates a pixel indent. It takes an integer value as its property. This integer represents the number of pixels to indent. The style placed after the indent keyword is placed horizontal to the current position in the layout. When styles are being placed across, indent indents the following style relative to the previous one. When styles are being placed below, indent indents the following style relative to the left edge of the current virtual column. The following example illustrates how indent behaves under both these circumstances:

view layout [
    subtitle "Going ACROSS"
    across
    button "one" indent 25 button "two" return
    below
    subtitle "Going BELOW"
    button "three" indent 25 button "four"
]

This produces the following window:

Pad

The pad keyword creates extra padding between styles. It uses a pair or integer value. When it is an integer, spacing is created either horizontally (across) or vertically (below). When it is a pair, the spacing will be created both horizontal and vertically. The following example illustrates both uses. First, the buttons "one" and "two" are padded with an integer representing 40 pixels in one direction. Then the buttons "three" and "four" are padded with a pair representing 40x40 pixels.

view layout [
    across
    button "one" pad 40 button "two" return
    button "three" pad 40x40 button "four"
]

The effect is the buttons "one" and "two" with a padding of 40 pixels between them horizontally. As well,  the buttons "three" and "four" are padded with 40 pixels between them both horizontally and vertically:

Tabs and Tab

The tab keyword positions styles at specified pixel "tabstops". Tabstop direction is relative to whether elements are being placed horizontally or vertically. That is to say, if the across keyword is used prior to tab, then styles will be tabbed horizontally. If it is the below keyword, then it will be vertical.

Tabstops are set with the tabs keyword. The tabs keyword uses a single property. This is either a block containing integer values or a single integer value. When it is a single integer, all tabs will be space to that number of pixels relative to the top left edge of the window. When it is a block of integers, tabs will space to the pixel tabstops set in the block relative to the top left edge of the window. By default, tabs is set to 100 pixels. The following examples illustrate how each of these approaches work.

Setting tabstops to 75 pixels. The button's "one", "two", and "three" are tabbed across.

view layout [
    tabs 100
    subtitle "Three Buttons"
    across button "one"  tab button "two"  tab button "three"
]

This displays the following window:

Setting two tabstops at 30 and 75 pixels. Field, checkbox and text styles are used in this example:

view layout [
    tabs [30 75]
    across
    text "email:" tab field tab check return
    text "phone:" tab field tab check return
    text "fax:" tab field tab check
]

This creates the following window:

At

The at keyword tells layout to place a style at a specific location. Taking the first three buttons from the previous examples, the following example uses the at keyword to place a button at three different coordinates within the layout. These are the pair coordinates 50x50, 100x100 and 150x150:

view layout [
    subtitle "Three Buttons"
    at 50x50 button "one"
    at 100x100 button "two"
    at 150x150 button "three"
]

The above example displays the following window:

Position Keywords Return Their Location

If no pair property is used with at, it will simply return the current position within the layout. In fact, all of the position keywords return their current or passed coordinates as a pair. This next example shows how the pair positions returned from position keywords can be assigned to a word and used. This example only uses across, below, guide, return and at, but any of the position keywords will return a pair value. This pair value represents the position moved to within the layout when the keyword was used:

view layout [
    a1: across b1: button "across" [b1/text: to-string a1 show b1]
    g:  guide  b3: button "guide"  [b3/text: to-string g show b3]
    r:  return b4: button "return" [b4/text: to-string r show b4]
    a2: at     b5: button "at"     [b5/text: to-string a2 show b5]
    b:  below  b2: button "below"  [b2/text: to-string b show b2]
]

The above creates a display with five buttons:

Clicking any of the buttons will replace its label with the pair position returned by the position keyword used just prior to the button in the layout. The following image shows the result of clicking on all the buttons:

This demonstrated another very important feature of VID. Any of the style keywords can be preceded by a set-word. This word will be set to the face that represents the style being placed. At any time, this word can be used to change and redisplay the face. The Face Details section gets into the guts of face definitions.

Action Keywords

There are three action keywords. The first is do, the second is style and the last styles. The do keyword evaluates a block within the layout. The style keyword creates a new style keyword and styles sets VID to use a pre-defined style sheet. Style sheets along with these two keywords are explained in the next section, Style Sheets.

The do keyword uses one defining property, a block that is evaluated. Use do to help with initializing layout styles. For instance, when dynamically modifying the properties of styles. The following example sets a button's label to the opposite of the value set in state:

state: false
view layout [b1: button do [b1/text: complement state show b1]]

This displays the following:

If state evaluated to true, then the button would be labeled "false".

Styles Sheets

Styles is really the basis for everything when developing REBOL/View applications. Existing styles may be modified or new styles created and added to VID. This was touched upon lightly earlier.

The stylize function creates style sheets. A style sheet can be used in VID to define a new set of styles. This includes the redefining of existing styles. Style sheets are used by layout. The stylize function takes a single block as its argument. The block contains sets of three elements. Each of the element sets define a new style within the style sheet. These consist of two words and a block.

The first word is the style being created or modified. The second word is the template style being used to create the new one. The block is a definition block used to declare the differences between the template and the style being created or modified. This definition block uses the facet names of a face to define the new style. The following example shows a silly, but illustrative example of creating a new style sheet:

new-styles: stylize [
    red-button button [color: red]
    green-button button [color: green]
    blue-title title [font: [color: 190.190.255]]
    pink-title title [font: [color: 255.200.200]]
    text text [font: [color: yellow]]
]

The above example creates the style sheet new-styles. This style sheet contains four new styles and modifies one existing VID style. The four new styles are red-button, green-button, blue-title and pink-title. The modified style is text.

The styles keyword is used to set the current user defined style sheet:

layout [styles new-styles ...]

This style sheet is placed over the default. This is what allows default VID styles to be redefined. After using styles to identify a style sheet, the styles defined in the style sheet may be used:

view layout [
    styles new-styles
    blue-title {Ready! Get set!}
    across
    green-button "Go!" red-button "Stop!"
    below
    pink-title "It's up to you!"
    text "DISCLAIMER: this is all just a figure of speech"
]

The above example uses all the styles defined in the new-styles style sheet. First the style sheet is set in the layout with styles. Then the blue-title style is used followed by the green-button and red-button. After the buttons the pink-title is used and finally the redefined text style. This creates the following display:

Using styles allows template face objects to be setup and used as needed. When developing a user interface, the style sheets are first created with stylize and then used in VID with layout. A style can be created from anything that can be done with a face. Creating many styles for things like text, paragraphs, fields and buttons allows the implementation of a user interface to be approached in the most simplistic fashion. The user interface developed has a consistent look and feel. When the look and feel needs to change, all that may need to change in the script are the style sheet definitions.

The get-style function returns the face object of a default style. The following example will print out the structure of the face associated with VID's button style:

probe get-style 'button

The Face Object

All user interface elements are faces. Even the main window is a face. It is the parent face. Every element used in a REBOL/View user interface is a face placed within a pane sub pane of the parent face. The following sections discuss the fundamental behaviors and structure of faces.

First positions and sizes are covered. This talks about how faces are positioned relative to each other and sizing them. Then the face facets are explained in detail. Each face facet is documented. Some of them include brief examples of how they would be used.

Positions and Sizes

Positions, sizes and offsets use the default coordinate system. The default coordinate system uses pixels. However, a virtual coordinate system can be used to make the display resolution-independent. This allows the same display to be made smaller or larger for other types of devices such as televisions or hand-helds LCDs. The virtual coordinate system is discussed later.

The position of a face is specified relative to the inside edge of its parent. The size of the area it will occupy also can be provided. Unless otherwise specified, the main window's face will adopt the size facet of the face used to create the window. A face's offset is relative to the main window, as illustrated in the following diagram:

When faces are added to the pane facet of a face, they become sub faces. A sub face or group of sub faces is called a pane. The offset facet is used to indicate the pane's offset within its parent. This offset starts at the top left corner of a face. For instance, the following example displays a white window (parent face) with a tan beige pane offset to 120x100 pixels inside the parent face:

view make face [
    size: 385x260
    color: 255.255.255
    pane: make face [
        text: "Sub Face"
        size: 150x90
        offset: 120x100
        color: 245.193.122
    ]
]

The above example displays:

A similar effect can be accomplished with layout:

view layout [
    size 385x260
    backdrop 255.255.255
    at 120x100 box "Sub Face" 150x90 245.193.122
]

For faces inside of panes, the same positioning method is used. Every face positioned inside the pane of another face is offset relative to the inside border of the parent face.

This allows free relocation of the sub-faces within the pane. When a face is moved, all of its sub-faces will move along with it. In many cases, a pane will not provide any additional graphics, but will be used for grouping face objects. For instance, the following examples display the three layers of faces shown in the illustration above.

First, the parent face:

parent-face: make face [
    size: 385x260
    color: 255.255.255
]

Second, the first sub face. Since the body is white, a black edge is created:

sub-face: make face [
    size: 140x150
    offset: 40x30
    color: 255.255.255
    edge: make edge [color: 0.0.0]
]

Third, the two third layer sub faces. Here the face bottom-face is created with the primary data. From it two faces are created with differing offsets. These are bottom-face1 and bottom-face2.

bottom-face: make face [
    text: "sub face"
    size: 60x30
    color: 64.128.64
]
bottom-face1: make bottom-face [offset: 40x20]
bottom-face2: make bottom-face [offset: 40x70]

Finally, viewing the lot of them. There are many ways to do this. The following example uses view to display the parent-face. Inside the parent face the pane facet is defined to sub-face. Inside sub-face the pane facet is defined to a block that contains bottom-face1 and bottom-face2:

view make parent-face [
    pane: make sub-face [
        pane: [bottom-face1 bottom-face2]
    ]
]

This produces the following window:

Again, a similar effect can be accomplished with stylize and layout:

stylize [my-panel panel [edge: [size: 2x2 color: 0.0.0]]]
stylize [my-box box [
    size: 60x30 color: 64.128.64
    font: [size: 12 color: 0.0.0 shadow: none]
]]

view layout [
    size 385x260
    backdrop 255.255.255
    at 40x30 my-panel 140x150 [
        at 40x20 my-box "sub face"
        at 40x70 my-box "sub face"
    ]
]

Face Facets

The facets of a face determine what the face will look like when it is displayed. The standard face object is defined in system/standard/face as:

face: make object! [
    offset: 0x0         ; position (position of window)
    size: 100x100       ; width & height (dimension of window)
    span: none          ; offset to next area (scaling factor)
    pane: none          ; sub-face or block of surfaces
    text: none          ; face text (window name)
    data: none          ; user defined data field
    color: 128.128.128  ; color of the face's background
    image: none         ; loaded image placed in the face
    effect: none        ; effect settings for image or background
    edge: object!       ; describes the edge border
    font: object!       ; describes the font attributes
    para: object!       ; describes the paragraph attributes
    feel: object!       ; the functional behavior of the face
]

For convenience, this is also defined as the global word face. Following is a more detailed description of the object fields of a face:
 
Face Object Definition
offset pair

The X-Y position of the face relative to its parent face. If scaled coordinates are being used, then offset will be the scaled value. Example:

offset: 10x10
size pair

The width and height of the face's area. It is the size of the face's body. By default, clipping will be performed to prevent internal graphics (including text) from spilling outside this area. Example:

size: 1000x1000

span pair For the top-level face, span specifies size of the virtual coordinate space. For instance, providing 10000x10000 specifies the coordinate of the display's lower right corner. For all other faces, span specifies the offset for each iterative face when an auto iteration is being performed. This facet is set with the /span refinement when using view to display a new window. More is explained below in Virtual Coordinate Space.
pane face
block

A face or block of faces that are located relative to the face and displayed within its bounds. Example of a single-child display object:

pane: make face [
    offset: 10x10
    text: "display object inside a display object"
]

Example of multiple-child display objects:

pane: reduce [
    make face [
        offset: 10x10
        text: "FIRST child display object"
    ]
    make face [
        offset: 10x110
        text: "SECOND child display object"
    ]
]

text value

A string (or any other value, such as a number) to be displayed within the face. The string may be a single word or an entire paragraph. The font, color, size, alignment, and other attributes of the text are determined by the font and para facets. Example:

text: {any text string inside of quotes "" or braces {}.}

data value An open variable storing other information about the face. Strictly, data is not required because the face object can be extended with additional fields as needed.
color tuple

The color of the face's body. If an image is specified, it indicates the tint to be applied to the backdrop behind and around the image. The primary color specified for the area. How it is applied depends on the rendering performed. For flat shading, it is the fill color. For transparency colorizing, textures, gradients, it is the primary hue. Note that, in some cases, multiple colors may be needed. They can be specified in the effect arguments.

color: 80.100.80

image image

An image to use for the face's body. The image can be scaled to fit the face when needed. This is done with the effect attribute.

image: load %stars.jpg

effect word
block

Renders the image or face background. Many image processing effects are available. More than one rendering operation can be used at time to create the final effect on the face or image. A single effect may be used as a word, or multiple effects as a block of words. When using multiple effects, the effects will render in the order they appear in the block. The effects are explained in the Effect Attributes table below.

Example:

image: load %bay.jpg
effect: [hflip fit blur colorize 200.200.200]

The above example will flip the image bay.jpg horizontally, then span it to the size of the face, blur it a little and finally recolorize it as a light gray.

edge object The attributes of the edge area. It includes color, image, special effects, and the size of the edge. This object's attributes are explained below.
font object The attributes of the font used for text display. It includes the font name, style, size, color, offset, space, align, valign, angle, shadow, and outline. This object's attributes are explained below.
para object The attributes of the paragraph used for text. Includes the origin, margin, indent, tabs, edit, wrap, scroll, and filter. This object's attributes are explained below.
feel object Four functions that define the behavior of the face. The functions are evaluated at various times during the rendering, selection, and hovering over a face. This object's attributes are explained below.
rate integer
time

Specifies rate of update. Each update will evaluate the engage function in the feel object of the face. The action sent to the engage function will be 'time:

my-face/rate: 0:0:05

The example will cause the function defined to my-face/feel/engage to evaluate every five seconds. If my-face is shown with show in the function, the face will be re-rendered every five seconds.

options block
word

Set options in the top-level face object shown with show to affect the behavior of the window opened. An option may be set with a word, or multiple options set with a block of words. Options set in sub faces are ignored:

  1. no-title - Window will have no title bar 
  2. no-border - Window will have no border, this is overridden if resize is set 
  3. resize - Window will be resizable 
  4. all-over - Indicates that over events send continuously as the mouse is moved within the face. The default is to send only one over event will be sent upon entering into a face. 

When using view, set the option with view's /options refinement. This refinement takes a single argument of either a word or block of words.

line-list block
none
This attribute keeps track of data relating to the text attribute when the amount of data in the text attribute reaches or exceeds 200 characters. This attribute should be set to none when data in the text or font attributes change. This allows REBOL to recalculate the way the text is displayed when the face is redrawn.

The facets span, pane and text can be set to none to be ignored. A number of facets are sufficiently complex that they are best described with objects. An advantage of using objects is that they can incrementally be refined through inheritance. There are four facet objects. These are edge, font, para and feel.

Edge Facet Object

The edge is a rectangular subframe that borders the inside of a face's body. It is used for image borders, button edges, tables, special framing, etc. It is composited with the face and has following attributes.
 
Edge Attributes
color tuple

The color of the edge.

Example:

edge: make edge [color: 30.50.30]

image image

An image to use for the edge. The edge is placed behind the face's body. 

Example:

edge: make edge [image: load %ivy.jpg]

effect word
block

An effect used to render the edge. Uses all the same effects that can be used in the face's effect property. Refer to the Effect Attributes table below. Identical to the face's body rendering, except processing may not be performed on the rectangle obscured by the face's body. 

Effects unique to edges are:

  • bevel - shadow on bottom and right edges 
  • ibevel - shadow on top and left edges 
  • bezel - indented shadow on left and right edges 
  • ibezel - the inverse of the ibezel effect
  • nubs - rectangular nubs at each of the four corners and sides in the edge

Example:

edge: make edge [effect: 'bevel]

size pair

The pixel thickness of edge as an x/y offset. The x offset refers to the thickness of the vertical borders (left and right) while the y offset the horizontal borders (top and bottom). 

Example:

edge: make edge [size: 4x4]

Font Facet Object

Following are the standard text style attributes.
 
Font Attributes
name word
string
block
The name of the font. (A list of font names may also be used.)
style word
block
The style of the font (plain, bold, italic, etc.)
size integer The size of the font.
color tuple The text color of the font.
offset tuple Padding.
space pair Spacing between characters and between lines. The x value adds to the spacing between characters. Positive values expand the text, negative values condense it. The y value has a similar effect on line spacing.
angle integer The baseline angle of the text in degrees.
align word The alignment (left, center, right, justify, top and bottom)
valign word The vertical alignment (left, center, right, justify, top and bottom)
tabs integer
block
Tab spacing can be specified as a repeating fixed distance (integer) or at specific locations on a line as a block of integers.
shadow pair
block
Specification of a shadow effect. (requires offset, percentage, color)
outline integer
block
Specification of an outline effect. (requires size, color)

Paragraph Facet Object

Paragraph facet object attributes are applied to entire paragraphs of text for control of spatial formatting. They only apply to text rendered within areas, so are not used for free-form text.
 
Paragraph Attributes
origin pair Offsets the text origin from the left top of the bounding area. This is needed because the bounding area may be sized for reasons other than the proper positioning of text (e.g. for an image size or graphic).
margin pair Prevents text from entering a region on the right and bottom of the area. If text enters this area, word wrapping will occur. Necessary for the same reasons as origin.
indent pair Offsets the origin of a new paragraph's first line. The X value can be used to indent or exdent (negative value) the start of the line. The Y value is used only to add extra spacing between paragraphs. It is ignored for the first paragraph.
tabs integer
block
Tab spacing can be specified as a repeating fixed distance (integer) or at specific locations on a line (a list of integers).
edit? logic Indicates that the text can be edited. Used for editable string fields.
wrap? logic Indicates that word wrapping is desired.
scroll? logic Indicates that scrolling is desired.
filter func Filters that are applied to text during edit mode. A function that can be used to prevent specific types of characters from being entered.

Feel Facet Object

The feel facet is the face's behavior in response to mouse input and other events. You can control what happens to a face each time it is drawn, hovered over, or selected. The feel object within a face defines the functions to be used. The following table provides a brief overview of the feel facet. There is more to it. This is explained in much greater detail after REBOL/View's event processing system is talked about in Events.
 
Feel Attributes
redraw func Called immediately before a face is displayed. This allows a face to dynamically alter any of its facets prior to being displayed. This is how screen interacts (buttons, choices, etc.) reflect their current state to the user. For example, a button can be displayed as either up or down depending on the state of a variable that has been set. The redraw variable should be set to none if no function is needed. This speeds up the interface by not calling unnecessary functions.
detect func Called every time an event passes through the face. This allows events to be handled and filtered. To handle events globally, define a function to system/view/screen-face/feel/detect before calling view to create the first window.
over func Called whenever the mouse pointer passes over the face while the select button is up. This function can be used to provide user feedback by changing the appearance of the face. For instance, hot text can change color as the mouse passes over it.
engage func Called when the select button goes up or down on a face. When the face is selected with a mouse down event, this function will be called with move events until the button is released. These combinations allow the state of the face to change depending on the actions of the mouse. This typically performs some type of action based on the selection.

This function is also called at the rate specified in the rate attribute. For instance, if the rate is set to 10 or 0:0:10, it will be called every ten seconds.

Face Effect Properties

Face effects are used in the effect and edge/effect facets. They are normally used in a block. The effects that don't use arguments can be used as a word if it is the only effect being used. However, when more than one effect is to be used, they must be grouped in a block. Effects are accumulative. In other words, they are rendered in the order they appear. This accumulative rendering promotes being able to create advanced rendering effects. For instance, an image may be grayscaled before colorizing it.

Following is a list of effects. The left column lists the effect names and, when applicable, their arguments. Mandatory arguments are bold italics while optional arguments are plain italics. To the right of each is a description of what the effect does.
 
Effect Properties
tile Tiles image relative to the face.
tile-view Tiles image in the face relative to the window.
vflip Displays the face's image flipped vertically.
hflip Displays the face's image flipped horizontally.
fit Spans the image to the size of the face.
aspect Spans the image to the size of the face without changing the image's aspect ratio. The image will fill up the face either horizontally or vertically depending on which dimension is reached first as it spans.
blur Displays the face's image blurred. This effect may be used multiple times and is cumulative.
sharpen Displays the face's image with a sharpen filter. This effect may be used multiple times and is cumulative.
contrast Displays the face's image with a contrast filter. This effect may be used multiple times and is cumulative.
emboss Displays the face's image with an embossed effect.
invert Displays the face's image with it's RGB values complemented.
clip Clip the image to the size of the face. Used when the face is smaller than the image and the entire image doesn't need to be rendered. The image is clipped at the time clip appears in the effects block, so other effects such as hflip and vflip can be rendered on the image before clipping it.
grayscale Displays the face's image grayscaled.
cross tuple Displays the face with a cross through it. The tuple color argument is optional. It specifies the color of the cross when used. The cross is medium gray by default.
oval tuple Displays the face with a circle in it. The tuple color argument is optional. It specifies the color of the circle when used. The circle is medium gray by default.
arrow tuple Displays the face with an arrow in it. The tuple color argument is optional. It specifies the color of the arrow when used. The arrow is medium gray by default.
key tuple Sets a color in the face's image as transparent.
colorize tuple Colorizes the background or image. Must be used in a block with one argument. The argument is an RGB tuple value.
brighten integer Lightens the background or image. The higher the number, the greater the brightening effect. Maximum effect is reached at 255.
tint integer Creates a tint on the background or image. The integer determines the phase of the tint.
gradient pair tuple tuple Displays a color gradient over the background or image. The pair value represents a vector indicating where the gradient begins. Both the x and y coordinates use a value between 1 and -1. The x coordinate of the pair represent the horizon