![]() |
Return to Old Documentation Archive |
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 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.
|
| /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:
This example displays a window with a top left corner 30 pixels
in and 10 down |
| /style | block |
A block defining the face attributes of the top level face. Any of the face attributes may be defined:
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:
The above example starts placing images with no padding. |
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:
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.
|
| /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:
|
|
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.
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:
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:
|
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.
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 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.
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
...
]
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:
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:
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:
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:
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:
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:
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:
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.
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 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
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, 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"
]
]
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:
|
| 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:
Example of multiple-child display objects:
|
| 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:
|
| 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.
|
| 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.
|
| 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:
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:
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:
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.
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:
|
| image | image |
An image to use for the edge. The edge is placed behind the face's body. Example:
|
| 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:
Example:
|
| 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:
|
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 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. |
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 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 horizontal left and right vectors. The y represents the vertical top and bottom. A 1 represents the left or top while a -1 represents the right or bottom. A 0 indicates no vectoring. So to start a gradient in the top left corner, the pair would be 1x1. The gradient will end directly opposite the beginning vector. The first and second tuple color values are optional. By default, the gradient will go from black to the background color. When only the first tuple value is provided, the gradient will go from that color to black. When both tuple values are provided, the gradient goes from the first color to the second. |
| gradmul pair tuple tuple | Displays a multiplied gradient on the background or image. The pair value is used the same as with the gradient effect. The two tuple values are optional and also behave similar to the gradient effect. When no tuple value is provided, the gradient goes from multiplying by black to multiplying by a the background color. When the first tuple value is provided, the gradient goes from multiplying by that value to multiplying by the background color. When both tuple values are provided, the gradient goes from multiplying by the first value to the second. |
| gradcol pair tuple tuple | Displays a colorized gradient on the background or image. Follows the same rules as the gradmul effect. But, instead of a multiplying by the provided tuple values, it colorizes with them. |
| rotate integer | Displays a face's image rotated by the degree set as integer. Must be used in a block with one argument. The argument is an integer indicating the degree of rotation. Currently the only degrees of rotation supported are 90, 180 and 270 degrees. |
| reflect pair | Displays an image with one half reflecting the other. The pair value represents the vector to reflect. That is, which half of the image will be reflected. The accepted vectors are 1x0, -1x0, 0x1 and 0x-1. These represent the reflection of the left, right, top and bottom, respectively. |
| crop pair pair | Displays the cropped portion of the image defined to the face's image property. Must be used in a block with two arguments. The first argument is the starting position of the crop. The second argument is the size of the crop. |
Events consist mostly of mouse activity and keyboard input. They are actual REBOL values of the event! datatype. There are four categories of events. These are mouse, keyboard, window and time events. Mouse events occur during motion and button selection. Keyboard events occur when a key is pressed. Window events occur when a window becomes active, inactive, resized or closed. And, time events occur every clock tick of the computer's internal clock.
These events can be trapped and handled. This is accomplished by defining functions to the properties of a face's feel facet. By default, these properties are defined as none. Each of the feel facet's four properties help to address specific types of events. For instance, a function defined to a face's over property will be called every time the mouse cursor enters or leaves that face.
Most of the styles in VID have defaults set to the face's feel facet. These or any other facet defined in a style's face can be looked at using the get-style function. This function is explained in Creating Face Layouts under Styles. Following is a brief example that will show the feel facet's properties for a style. This example looks at the box style:
probe get in get-style 'box 'feel
The one property that doesn't directly process an event is redraw. This function is simply called every time a face is redrawn. Faces are redrawn whenever the window is moved or resized. A face is also redrawn when show is called on it or one of its parent faces.
All events pass through the detect property. Every event occurring in a face is passed from the top-level face inherited from system/view/screen-face to the face the event occurred in. Each face it passes through can trap and handle events with its feel/detect function.
When a function is defined to any of the feel facet's properties, that function will be called with specific arguments. The arguments passed to the function depend on which property is being called. Properties defined to none are never called.
Some of the properties take an event value as one of its arguments. An
event value is represented as the event! datatype. Each event contains
information about itself that is accessible by using the refinements supported
within the event! datatype. The following table explains these
refinements:
| Event Refinements | |
| /type |
Returns event type. The event types are:
|
| /offset |
Returns the mouse cursor offset relative to the REBOL/View window. The offset returned has different meaning depending on the event type:
|
| /key | Returns the ASCII character relative to the
event. With 'key events, this returns the character
pressed that triggered the event. The only exceptions are the arrow
keys Up, Down, Left, Right, and the End and Home keys. These key events
are handled internally by REBOL for changing the caret position in
edit windows. These key events return word representations. The word
representations for the Up, Down, Left, Right, End and Home keys are
'up, 'down, 'left,
'right, 'end or 'home,
respectively. For the mouse up and down events as well as 'time , 'resize and 'move, the character returned is always #"^@", which is represented in REBOL as a null character. |
| /control | Returns a logic value, true or false, depending on whether the control key is pressed when the event is sent. This works with the mouse up and down events as well as 'move, 'key, 'resize and 'time. |
| /shift | Returns a logic value, true or false, depending on whether the shift key is pressed when the event is sent. This works with the mouse up and down events as well as 'move, 'key, 'resize and 'time. |
| /time | Returns an integer representing a unique time index for the event. |
| /face | Returns the top-level face object of the window that was active when the event occurred. |
These refinements allow events to be examined and actions determined based on the event characteristics.
For example, to see if the event is a left mouse click, check the event type using the /type:
if event/type = 'down [ ... ]
This next example checks whether the shift button is held down when the mouse-down event occurred:
if all [(event/type = 'down) (event/shift)] [ ... ]
Following illustrates how different types of events can be handled:
...
switch event/type [
down [ ... ]
up [ ... ]
key [ ... ]
close [ ... ]
]
...
Typically, the characteristics of an event will be checked in a function defined to a face's feel/engage, or feel/detect property. These are the two properties of the feel facet that take an event value as one of its arguments.
To process events focused on a specific face, use a face's feel
object. Every face has a default feel object with four words defined
to none. These words, collectively referred to as feelings,
are redraw, detect, over, and
engage. Each relate to specific events that occur in the
face. Feelings are functions that create actions based on events occurring
within the face. The following table explains the feelings and when they
are called:
Each of the feelings listed previously take as their first argument its own face object. This allows the feeling to modify its face object before reshowing it with show. When show is called within a feeling on the face passed, that face and its sub faces are redrawn in the REBOL/View window. Here's an example:
...
over: func [face [object!] over? [logic!] offset [pair!]] [
either over? [
face/text: "Mouse Is OVER This Face!"
] [
face/text: "Mouse is AWAY From This Face!"
]
show face
]
....
If a face's offset is changed before reshowing it, the face will be moved to that new offset in the REBOL/View window upon calling show.
The face feelings can be looked at using probe. For example:
probe face/feel
make object! [
redraw: none
detect: none
engage: none
over: none
]
The following information is provided to offer more detail on how the event mechanism works within REBOL. It is not pertinent to the user processing of events. Events are processed by the do-events function. This function is invoked when the first window is created with view.
Caution: Making changes to the do-events mezzanine is not recommended.
The do-events function first opens an events port using the 'events scheme:
event-port: open [scheme: 'event]
It defines event-port as a type of port called an event port. All events taking place in displayed REBOL/View window faces are queued in event-port. Each event queued is an individual event of the type event!.
Once the event-port is opened, do-events enters a while loop. The loop continues as long as there are face objects in system/view/screen-face/pane. Each iteration of the loop evaluates the next event in event-port with do. The evaluation of the event sends the event to the top level face and down the face hierarchy. When the while loop exits, event-port is closed.
The do-events function is a mezzanine and can be viewed using source:
source do-events
do-events: func [
"Process all View events."
/local event-port
][
event-port: open [scheme: 'event]
while [not empty? system/view/screen-face/pane] [
wait event-port
do first event-port
]
close event-port
]
Sometimes it is not practical to specify every face that is to be displayed. For instance, in the case of a file list or email inbox, there may be numerous identical faces that vary by content and position. In such cases, these faces can be generated dynamically through iteration.
To create an iterated view, the pane variable, which is normally set to a face or block, is instead set to a function. This function is called by the system to supply the pane face or block during the iteration process. For instance, the following example shows a simple function that can be defined to a face's pane. It is explained below:
face-list: func [size [pair!]] [
faces: copy []
size-mold: size
face-mold: make face [
color: 255.255.255
size: to-pair reduce [size-mold/x 20]
offset: 0x0
]
face-mold/text: rejoin [
"Offset: " face-mold/offset " - Color: " face-mold/color
]
while [face-mold/offset/y < size-mold/y] [
append faces make face-mold []
face-mold/offset/y: face-mold/offset/y + 20
face-mold/color: face-mold/color - 10
face-mold/text: rejoin [
"Offset: " face-mold/offset " - Color: " face-mold/color
]
]
faces
]
This face-list function takes a single pair value as its argument. This can be the size of the face that is using the function as its pane. This function also returns a block of face objects that were created in the while loop. All the above function does is initialize a simple face, face-mold, and then append this face to a block with each iteration of a while loop. Through each iteration the face's offset, text and color facets are changed. The "y" position of the offset is increased 20 pixels, the text is changed to reflect the new offset and the color is darkened a little. This results in a block of faces each with different offsets, colors and text values.
The following example shows how an iterative function can be used in a face. The above face-list example is used:
view make face [
size: 300x300
edge: make edge [size: 0x0]
pane: face-list size
]
This will produce the following window:
Functions can be used to iterate faces when the system needs to identify the faces that make up the iterated view, such as during display rendering or event processing.
A virtual coordinate space makes it possible to develop a visual interface without needing to know the actual display size. This is to say, it makes it possible to use a virtual pixel space for aligning face objects. So, the resolution of a user's display does not need to be known before designing a visual interface. For instance, say you want to create a visual interface that will look the same between systems with a maximum resolution of 320x240 and systems with resolutions of 1280x1024 and greater. This can be done with View's virtual coordinate space capabilities.
A window's virtual coordinates are defined in a window's top level face's span facet. To set the span, use the /span and /size refinements when using layout to display a new face. The /span will indicate the virtual coordinate space while /size specifies the actual pixel size of the window.
layout/span/size face 4096x3072 341x25
| |
Virtual Coordinate Space |
Window's Size (real pixel space)
The top level face is inherited from the global face object. Using the /span and /size refinement with layout will set the span and size facets within the top level face as it is inherited. The /size refinement must be used with the /span refinement to set the actual pixel size of the window. If the real pixel space window size is not set in this way, undesirable results may occur.
All sub faces used within the spanned face will use the virtual coordinate space specified. This includes the face argument passed to view. Every facet that uses pixel coordinates will also be affected by a virtual coordinate space. This includes the sizes of fonts, edges and paragraphs.
The example below shows the face object being passed to view as having the same size as the span that is set:
view layout/span/size [
...
] 4096x3072 341x256
This is because the face passed to view normally uses all available space. So, the virtual space needs to be used to accomplish this. Ideally, the pair value is set to a value larger than the highest resolution display that the View script will run in.
Using the iterative function defined in the previous section, the following example illustrates the effect defining faces that do not take advantage of a virtual coordinate space:
view make face [
size: 300x300
pane: make face [
size: 900x900
span: 900x900
edge: make edge [size: 0x0]
pane: face-list size
]
]
This results in displaying:
The reason the sub faces are so thin is because they are each set to a height of 20 pixels. Because the virtual pixel space is set to 900x900, the faces end up being displayed at a third of the height of 20 pixels. This problem can be rectified by modifying the face-list function that was used in creating the above window to take advantage of the virtual coordinate space.
Notice the width of the sub faces successfully scaled to the virtual coordinate width of the face. This is because that was handled dynamically. Here is a modified version of the face-list that assigns sizes and offsets dynamically:
face-list: func [size [pair!]] [
faces: copy []
size-mold: size
heights: size/y / 15 ; will result listing 15 sub faces
face-mold: make face [
color: 255.255.255
size: to-pair reduce [size-mold/x heights]
offset: 0x0
; virtual space is three times the real pixel space
font: make font [size: size * 3]
edge: make edge [size: size * 3]
]
face-mold/text: rejoin [
"Offset: " face-mold/offset " - Color: " face-mold/color
]
while [face-mold/offset/y < size-mold/y] [
append faces make face-mold []
face-mold/offset/y: face-mold/offset/y + heights
face-mold/color: face-mold/color - 10
face-mold/text: rejoin [
"Offset: " face-mold/offset " - Color: " face-mold/color
]
]
faces
]
Following is the same use of view as that was used previously:
view/span/size make face [
size: 900x900
edge: make edge [size: 0x0]
pane: face-list size
] 900x900 300x300
This now results in display a window that doesn't have the previous distortion of the sub faces. Notice how the offset count throughout the sub faces uses the virtual coordinates:
This datatype represents a coordinate pair (x,y). A pair! value is specified as <number>x<number>, such as 100x100. REBOL translates pair! values directly:
probe type? 200x200 pair!
Pairs can be viewed by their individual coordinates using traditional REBOL means:
p: 640x480 probe first p 640 probe second p 480
All pair values support the /x and /y refinements. They allow the viewing and manipulation of individual pair coordinates.
Viewing individual coordinates:
probe p/x 640 probe p/y 480
Modifying individual coordinates:
p/x: 800 p/y: 600 probe p 800x600
To determine if a value is a pair! datatype, use the pair? function:
probe pair? 400x200 true probe pair? p true
Use to-pair to convert block or string values into a pair datatype:
p: to-pair "640x480"
probe p
640x480
h
p: to-pair [800 600]
probe p
800x600
This datatype represents any loaded image. If an image's format is not supported by REBOL, it will fail to load. Use load to load an image file into REBOL.
Defining a word as an image:
img: load %bay.jpg
Once an image is loaded, it will be of the type image!:
probe type? img image!
To determine if a value is a image! datatype, use the image? function:
probe image? img true
The pixel values of an image may be obtained using pick and changed using poke.
Picking specific pixels:
probe pick img 1
51.69.179probe pick img 3000
98.225.0
Poking specific pixels:
poke img 1 255.255.255
probe pick img 1
255.255.255poke img 3000 0.0.0
probe pick img 3000
0.0.0
Images support the /size refinement. Use this refinement to return the pixel size of the image as a pair value:
probe img/size 192x144
Empty images can be created by making an image using a pair. Use make with the image! datatype or to-image:
empty-img: make image! 300x300
empty-img: to-image 150x300
Snapshots of a face and all its sub-faces may be taken by creating an image using a face. This is also done using make with image! or to-image:
face-shot: make image! face
face-shot: to-image face
Refer to the previous section about Events.
Blocks are parsed similar to strings. A set of grammar rules specify the order of expected values. However, unlike parsing strings, characters, spaces, and line termination are of no concern. Parsing of blocks is done at the value level, making the grammar rules easier to specify and operation much faster.
Block parsing is the easiest way to create dialects in REBOL. Dialects are sub-languages of REBOL that use the same lexical form for all datatypes but allow a different ordering of the values within a block. That is, the values do not need to conform to the normal order required by REBOL (that of function argument ordering). Dialects are able to provide greater expressive power for specific domains of use. For instance, the parser rules themselves are specified as a dialect of REBOL; so are function argument specifications.
A few concise examples help illustrate parsing of blocks.
block: [when 10:30] print parse block ['when 10:30] print parse block ['when time!] parse block ['when set time time! (print time)]
Note that a specific word can be matched by using its literal word in the rule (as in the case of 'when). A datatype can be specified rather than a value, as in the time! lines above. In addition, a variable can be set to a value with the set operation.
Alternates can be used as with strings:
rule: [some [ 'when set time time! | 'where set place string! | 'who set persons [word! | block!] ]]
This rules allows the information to be entered in any order:
parse [ who Fred where "Downtown Center" when 9:30 ] rule print [time place persons]
The example can use variable assignment, but it illustrates how to provide alternate input ordering.
Following is another example that evaluates the results:
rule: [ set count integer! set str string! (loop count [print str]) ] parse [3 "great job"] rule parse [3 "hut" 1 "hike"] [some rule]
Finally, following is a more advanced example:
rule: [ set action ['buy | 'sell] set number integer! 'shares 'at set price money! (either action = 'sell [ print ["income" price * number] total: total + (price * number) ][ print ["cost" price * number] total: total - (price * number) ] ) ] total: 0 parse [sell 100 shares at $123.45] rule print ["total:" total] total: 0 parse [ sell 300 shares at $89.08 buy 100 shares at $120.45 sell 400 shares at $270.89 ] [some rule] print ["total:" total]
Most of the same parse operations and formats that are available for strings are also allowed for blocks.
| - alternate rule [block] - sub-rule (paren) - evaluate a REBOL expression
none - match nothing opt - zero or one time some - one or more times any - zero or more times 12 - repeat pattern 12 times 1 12 - repeat pattern 1 to 12 times 0 12 - repeat pattern 0 to 12 times
skip - skip a value (or multiple if repeat given) to - advance input to a value or datatype thru - advance input thru a value or datatype
set - set the next value to a variable copy - copy the next match sequence to a variable
word - look-up value of a word word: - mark the current input series position :word - set the current input series position
In addition, a specific value can be matched when parsing blocks. For instance:
"fred" - matches to the string "fred" %data - matches to the file name %data 10:30 - matches to the time 10:30 1.2.3 - matches to the tuple 1.2.3
This can be done for any datatype with the exception of integers, which are reserved for use as repeat counters. (However, the integers can still be matched; see below.)
In addition to match against a word, specify the word as a literal:
'name 'when 'empty
A value of any given datatype can be matched by specifying the datatype name. For example:
string! - any quoted string time! - any time date! - any date integer! - any tuple
Note: Don't forget the "!" that is part of the datatype name or an error will be created.
The parse operations not allowed for blocks are those using specific characters. For instance, a match cannot be specified to the first letter of a word or string, nor to spacing or line termination.
When parsing a block, if a sub-block is found, it will be treated as a single value of the block! datatype. However, to parse a sub-block, invoke the parser recursively on the sub-block.
The into function expects that the next value in the input block is a sub-block to be parsed as if a block! has been provided. If it is not a block, then it will fail the match and look for alternates or exit the rule. If it is a block, the parser rule that follows the into function is used to begin parsing the sub-block. It is processed in the same manner as a sub-rule.
rule: [date! into [string! time!]] data: [10-Jan-2000 ["Ukiah" 10:30]] print parse data rule
All of the normal parser operations can be applied to the into function.
rule: [ set date date! set info into [string! time!]] ] data: [10-Jan-2000 ["Ukiah" 10:30]] print parse data rule print info rule: [date! copy items 2 into [string! time!]] data: [10-Jan-2000 ["Ukiah" 10:30] ["Rome" 2:45]] print parse data rule probe items
REBOL Technologies is very interested in the problems found. To report a bug, use the feedback script included with this release. Start REBOL/View, then enter feedbackat the prompt. If your REBOL system is configured to send email, the script will prompt for information, then email it directly to our support department.
Alternately, send an email message (no HTML or enclosures). Please write a subject line that describes the problem. Write something like "making blocks does not work" rather than just "bug". Email:
feedback@REBOL.com
We will send an automatic confirmation of each report. If you don't get the confirmation, verify that the email was sent and that the return address is correct.
Be sure to give us a simple example of the problem within the bug report. If it occurs in a large script, edit it down to just the bug. Please don't send large files.
Also include the version number as is printed in the title banner. It indicates not only the version and revision, but also the update number and the platform . From the REBOL language you can obtain the version number with:
print REBOL/version
|
Old Documentation displayed with permission from REBOL Technologies. |