Skip to content

Forms and Widgets

A form is a plain-text file (.per) that describes a screen: where the fields are and what kind of control each one is. You compile it with fcompile -xml, and the VDC client turns it into a real window with native buttons, date pickers, drop-downs and so on. You never write GUI code by hand.

This chapter covers the structure of a form file and the full catalogue of field types (widgets) and their attributes.

Anatomy of a form file

A form has up to four sections, in this order:

DATABASE ...          -- which database the fields belong to (or FORMONLY)

SCREEN  or  LAYOUT    -- the visual layout
{
   ...the picture of the screen...
}

ATTRIBUTES            -- bind each field tag to a variable and choose a widget

INSTRUCTIONS          -- optional: delimiters and SCREEN RECORD definitions (for lists)

The DATABASE line

DATABASE FORMONLY

Use FORMONLY when the fields are not tied to a database table (the form just collects values). When a form is bound to a table, name the database instead and bind fields to columns — covered in chapter 6.

The layout: SCREEN vs LAYOUT

For a simple fixed screen, use SCREEN { ... }. Text is drawn literally; a field is written as a tag inside square brackets. The width of the brackets sets the field width.

SCREEN
{
    Registration

    First name:  [f_first              ]
    Last name:   [f_last               ]
    E-mail:      [f_email                            ]
    Birth date:  [f_dob      ]
}

For grids, boxes and resizable layouts, use LAYOUT with containers — VBOX (stack vertically), HBOX (side by side), GRID, and TABLE (for lists). You will meet TABLE in chapter 5.

LAYOUT
 VBOX
  GRID
  {
    [f_first  ] [f_last   ]
    [f_email                          ]
  }
  END
 END
END

The ATTRIBUTES section

Each line connects a field tag (from the layout) to a variable and picks a widget type:

ATTRIBUTES

Edit  f_first = FORMONLY.first_name;
Edit  f_last  = FORMONLY.last_name;
Edit  f_email = FORMONLY.email, REQUIRED;
DateEdit f_dob = FORMONLY.dob;

The pattern is:

WidgetType tag = FORMONLY.variable_name [, attribute, attribute, ...] ;

If you omit the widget type, you get a plain edit field.

The widget catalogue

These are the field types the VDC client renders. Pick the one that matches the data.

Widget Use it for Renders as
Edit Single-line text or numbers Text box
Label Read-only caption or computed text Plain text (no input)
ButtonEdit A field with an action button (e.g. lookup) Text box + button
TextEdit Multi-line free text Multi-line text area
DateEdit A date Date field with a calendar
ComboBox One choice from a list Drop-down
CheckBox A yes/no value Check box
ProgressBar Showing progress 0–100% Progress bar
Browser Embedded HTML / a web view Mini web browser

Edit

The default field. Good for names, numbers, codes.

Edit f_qty   = FORMONLY.qty TYPE INTEGER;
Edit f_code  = FORMONLY.code, UPSHIFT, AUTONEXT;
Edit f_email = FORMONLY.email, REQUIRED;

Label

A read-only field — perfect for headings and computed results. You set its value from the program with DISPLAY.

Label f_title  = FORMONLY.title;
Label f_result = FORMONLY.result;

ButtonEdit

An edit field with a button on the right. Pressing the button raises an action your program can react to (typically a lookup / "pick from a list"). Give it an IMAGE (the icon) and an ACTION (the action name your code handles).

ButtonEdit f_customer = FORMONLY.customer, IMAGE="open", ACTION=f9;

Your program then reacts to that action inside an INPUT block (see chapter 4):

ON ACTION f9
    -- open a lookup, let the user pick, fill the field
A lookup dialog raised from a ButtonEdit action
A ButtonEdit action opens a lookup — here a customer search raised over the form. The client draws the dialog and its buttons; your code just reacts to the action and fills the field.

TextEdit

A multi-line text area, for notes and descriptions.

TextEdit f_notes = FORMONLY.notes, WANTTABS;

The variable behind a TextEdit is usually declared TEXT (or a long CHAR) in the program.

DateEdit

A date field with a pop-up calendar. The FORMAT attribute controls how the date is shown in this field, overriding the global DBDATE.

DateEdit f_dob   = FORMONLY.dob TYPE DATE;
DateEdit f_start = FORMONLY.start_date TYPE DATE, FORMAT="yyyy/mm/dd";
DateEdit f_end   = FORMONLY.end_date, NOT NULL, REQUIRED;

ComboBox

A drop-down. You can list the choices statically in the form with ITEMS, or fill them from the program at run time (shown in chapter 7).

ComboBox f_juice = FORMONLY.juice, ITEMS=("Apple","Orange","Tomato");

CheckBox

A yes/no control. TEXT is the label shown next to the box.

CheckBox f_agree = FORMONLY.agree, TEXT="I accept the terms";

ProgressBar

Shows a value between VALUEMIN and VALUEMAX. Update it from the program with DISPLAY.

ProgressBar f_prog = FORMONLY.progress, VALUEMIN=0, VALUEMAX=100;

Browser

Embeds a web view — useful for showing HTML help, a report preview, or a map.

Browser f_view = FORMONLY.url;
The Browser widget showing in-app HTML documentation
A Browser widget hosting live HTML — here the application's own documentation, served locally and shown inside the app window.

Field attributes

Attributes go after the variable, separated by commas. Here are the ones you will actually use, grouped by what they do.

Validation and input control

Attribute Effect
REQUIRED The field must be filled before the user can continue
NOT NULL The field may not be left empty/NULL
NOENTRY Display-only; the user cannot type in it
DEFAULT="…" Pre-fills a default value
PICTURE="…" Restricts input to a pattern
INCLUDE=(…) Restricts input to the listed values
AUTONEXT Jump to the next field automatically when this one is full

Appearance and behaviour

Attribute Effect
COLOR=… Text colour of the field
UPSHIFT Convert typed text to UPPERCASE
DOWNSHIFT Convert typed text to lowercase
HIDDEN Field exists but is not shown (you can reveal it from code)
FORMAT="…" Display format (dates, numbers)
TYPE … The field's data type, e.g. TYPE INTEGER, TYPE DATE

Widget-specific

Attribute Applies to Effect
IMAGE="…" ButtonEdit Icon shown on the button
ACTION=… ButtonEdit Action name raised on press
ITEMS=(…) ComboBox Static list of choices
TEXT="…" CheckBox Label next to the box
WANTTABS TextEdit Allow Tab characters in the text
WANTNORETURNS TextEdit Reject the Enter key
VALUEMIN / VALUEMAX ProgressBar Range of the bar

A complete worked form

Let's build a small "product entry" form that uses several widgets together. Create product.per:

DATABASE FORMONLY

SCREEN
{
    Product entry
    ----------------------------------------------------

    Code:        [f_code  ]
    Name:        [f_name                       ]
    Category:    [f_cat            ]
    Price:       [f_price    ]
    Active:      [f_active]

    Description:
    [f_desc                                     ]
    [f_desc                                     ]
    [f_desc                                     ]
}

ATTRIBUTES

Edit     f_code  = FORMONLY.code, UPSHIFT, REQUIRED;
Edit     f_name  = FORMONLY.name, REQUIRED;
ComboBox f_cat   = FORMONLY.category, ITEMS=("Food","Drink","Other");
Edit     f_price = FORMONLY.price TYPE DECIMAL(10,2);
CheckBox f_active = FORMONLY.active, TEXT="Active";
TextEdit f_desc  = FORMONLY.description, WANTTABS;

Compile it:

fcompile -xml product.per
A compiled form rendered by the VDC client
A form compiled from a .per file and rendered by the VDC — native widgets, with field-level help on a keypress.

The matching program — which opens the form, lets the user fill it, and reads the values back — is exactly what the next chapter is about.

Continue to Screens, Input and Menus.