REBOL Programming/Language Features/VID
VID stands for Visual Interface Dialect and is the most commonly used method for designing graphical user interfaces with REBOL/View. It works very well for interfaces that use a lot of graphics, e.g. images, animation.
One of the strong points of VID is that you can create a user interface very quickly, using only a couple of lines of code to make a button do something.
The GUI itself is platform independent, which means it looks the same whether you run your program on Windows, MacOSX, Linux or other platforms.
The most important thing to know about VID is that it is, as the name suggests, a dialect or sub-language of REBOL. Code written in VID does not evaluate as REBOL code, but has to be translated first into REBOL code prior to execution. In essence, a code generator called layout creates the REBOL code that is then executed by the REBOL View engine. Words used in the visual interface dialect may share the same spelling as normal REBOL functions, but are used completely differently.
view lo: layout [ button "Press Me" return button "Press Me Too!" ]
Here, layout takes a block of words written in the visual interface dialect. You can see the word return used here, but in this context, it has a totally different meaning. It is not used to return a value, but tells the layout engine to place the next button to the left of the screen, and on the next line. This different meaning of return also illustrates the context sensitive nature of REBOL programming.
layout returns a block of REBOL code, and in this example, it is assigned to the variable lo. If you were then to look at what code has been generated by
you will see screens and screens of code flashing before you.
Here are a few examples of what can be done with VID.
Need more examples
Each graphical element in a VID layout is called a face, which basically is a tree structure of objects. A face can contain other faces.
The full mechanics of faces and the face object will be explained in the next chapter.
The examples only show the layout code block, which means the block used for creating the layout. All examples should be written as:
view layout [button "Hello World!"]
while we only show:
button "Hello World!"
This makes it a bit easier to write the examples.
There are two kinds of buttons: BTN and BUTTON
btn "Hello World!"
This button is the standard type, and the easiest to use. It scales automatically with the text, but you can for example set a width for the button:
btn 150 "Hello World!" btn 150 "This is REBOL"
It's also easy to provide different colors and sizes for BTN:
btn 150x40 red "Big Red Button!" btn 200x20 yellow "Wide Yellow Button!"
BUTTON is different because it offers more customization in terms of coloring, edge size and gradients.
button "Hello World!"
In order to do something with the button, you can specify an action block. This is simply a block of code that is evaluated when the button is pressed, e.g. on left mouse button press. This block can be specified like so:
button "Hello World!" [print "Hello World!"]
When running this program, the console will print "Hello World!", every time you click the button.
A toggle is a button which has two states. There are two kinds of toggles: TOG and TOGGLE.
Like BUTTON, TOGGLE is customizable.
A choice is a button which has many states. It takes several strings to create the selection. Here is an example:
choice "Excellent" "Good" "Ok" "Lacking" "Dismal"
We can extend this example by providing code within a block. The state of the choice is held in c/data/1
c: choice "Excellent" "Good" "Ok" "Lacking" "Dismal" [print c/data/1]
Using this, we can trigger events based on a certain selection by using SWITCH:
c: choice "Excellent" "Good" "OK" "Lacking" "Dismal" [ switch c/data/1 [ "Excellent" [alert "Yeah!!!!!!"] "Good" [alert "Thank you!"] "OK" [alert "eh"] "Lacking" [alert "Come on!"] "Dismal" [alert "You can do better than that!"] ] ]
Simple lists are single column lists, which can be created with TEXT-LIST. The advantage is that it's very simple to access and is very useful in multi-list layouts, where multiple lists need to interact.
A simple list:
>> view layout [text-list data ["Hello World!" Rebol is Cool!]]
Complex lists provide a lot more functionality, but take more time to setup. With a complex list, you can use:
- Multiple Columns
- Varying font and color schemes
For a typical complex list, you use LIST:
l: list [ ... GUI code ... ] supply [ ... DATA code ... ]
The GUI code is a simple layout that represents one entry in the list. The layout can be as flexible as any other layout in VID and thus you can produce both vertical and horizontal layouts with text, graphics or images. Certain rules should be followed.
l: list 300x100 [across text text text] supply 
will produce an empty list of iterated faces.
The DATA code is the code to supply the list with data, and is a function that is iterated through out each single face in the list. Two variables index and count can be used directly to automatically iterate through your data in the function. The index value is used by each column of the list, while count specifies each row. For a list with 3 columns, the sequence will be:
ROW1 COLUMN1 ROW1 COLUMN2 ROW1 COLUMN3 ROW2 COLUMN1 ROW2 COLUMN2 ROW2 COLUMN3 ROW3 COLUMN1 ROW3 COLUMN2 . . .
For the list, the scroller is separate and should also be managed manually. It can also be placed where you want.
Events in the list layout can be used to select or display an over color when you hover the mouse over a list entry.
A complete example:
l: list 300x200 [ across text 200 bold text 50 red text 50 blue ] supply [ (complete this) ]
Manipulating Iterated Faces
The supply function can manipulate the list layout as you are iterating down through the list. This is nice when you want to make the text style, background color or other face attribute data dependent.
Alternating Background Colors Example
l: list 300x200 [ across space 0 text 200 bold text 50 red text 50 blue ] supply [ (complete this) ]
VID provides various functions for ordering your faces in a specific layout.
Using VID with resizing windows is a bit hard, but still possible: You need to detect when the window is resized and then redraw your GUI according to this new size.
Adhering to resizable layouts
To use VID with resizable faces, you need to know about the dimensions of your GUI.
VID has no direct functions for "attaching" faces to a specific size-dependent location of a GUI, so we need to carry out those calculations ourselves.
Panels are groups of VID faces. This has many advantages:
- Faces in a panel can be moved together
- Textfields in a panel can be updated together
Updating Panel Faces
When you have a form, that needs to be automatically filled, you can either fill out each field, one at a time, or group them in a panel, and update all fields at once using SET-FACE:
person: panel [ field field field ]
And updating all fields:
set-face person ["This" "is" "Cool"]
Not only strings can be used:
set-face person [25$ now http://www.rebol.com]
If you have other faces than fields, they can be skipped by inserting a NONE in the block:
person: panel [ field field box field ]
set-face person ["This" "is" none "Cool"]
TODO: Please check which faces, SET-FACE works on
In REBOL there is no real concept of a "main window", except for the console. If you close the console, you'll close all windows and quit the running program. If you have a script that is run from a double clicked script icon in Windows XP, you will be able to run your program without the console window and hence no main window.
It's possible to open as many windows as you want and they are equal in capability to each other and can control each other fully.
VID windows are really groups of faces, stored in another face object. This gives you the flexibility to present your GUI in a window or as part of a group of a larger GUI.
To open a single window, you normally use VIEW:
view layout [btn "Hello World"]
To open additional windows from this window, add an action to the BTN:
view layout [ btn "Hello World" [view/new layout [h1 "New Window"]] ]
VIEW/NEW is also useful, if you want to set variables or run other code, before capturing events from the created window.
Write something about DO-EVENTS.
Alerts are useful if you quickly want to display a dialog box with a message and a few buttons. It's a fast way to get user feedback. ALERT is the simplest one:
alert "This is an Alert Window"
will give the following:
REQUEST offers more flexibility with various button arrangements.
request "Do you want to Rock and REBOL?"
Styles are useful if you want more control over the visual appearance over a large section of faces. Let's say you want all buttons to be red? You can do that with stylize. You can produce a new kind of button that behaves differently from standard buttons. All parts of a face can be altered in your customized style. Styles are the easiest way to produce a customized, but uniform GUI look and behaviour.
Think of it as the style palette of a word processor. You can define a variety of styles, use them in your GUI and change them in a similar way to all the section headlines of your document. The concept is also similar to that of Cascading Style Sheets used with webpages and HTML.
There are two ways of using styles:
The 'style word is used within a layout:
view layout [ style my-btn btn red my-btn "Customized Button" ]
If you want a larger separate section of styles, you can define that as a block:
my-styles: stylize [ my-btn: btn red ] view layout [ styles my-styles my-btn "Customized Button" my-btn "Another Button" ]
This should probably be moved to View, as it's a more basic function than VID.
All faces share the same event system, which means the way to handle events for a face is the same for all faces. (true?)
To control events for a face, you use the FEEL keyword.
Images can be loaded into a VID GUI.