SIMPOL Documentation

Iterating Through dataform1 Elements

The technique for iterating through dataform1 elements is slightly different to that used in the wxform. Firstly, there are many different dring properties: controls, graphics, bitmaps, tables, datasources, detailblocks, links, siblinglinks, obgroups, and pages. Iterating through these drings is fairly consistent, but you need to know what to expect from each one, so that the varialbe used to hold the current item is correctly defined. Below is a table showing the dring and the type that a variable must be declared as in order to hold any given member of the dring.

Table 23.1. dataform1 dring Types
Ring Property NameRequired Type
controlstype(dataform1control)
graphicstype(dataform1graphic)
bitmapsdataform1bitmapsource
tablesdataform1table
datasourcesdataform1datasource
detailblocksdataform1detailblock
linksdataform1link
siblinglinksdataform1link
obgroupsdataform1optiongroup
pagesdataform1page


In each case the approach is the same:

Example 23.1. Iterating Through dataform1 dring Properties
function collectdf1controlnames(dataform1 f)
  type(dataform1control) c
  string names

  names = ""
  c =@ f.controls.getfirst()
  while c !@= .nul
    names = names + c.name + "{d}{a}"
    c =@ c.formnode.getnext()
  end while c =@= f.controls.getfirst()
end function names
          

In each case, the code tends to look very similar. It starts by getting the first item in the ring, then if that is not null (the ring has at least one entry), it enters the loop, processes whatever it is doing (the purpose for going through all the entries), then retrieves the next one in the ring, finishing when it has reached the first one again. In the prior example, since any number of different control types will be returned by the call to c.formnode.getnext(), the variable c is declared with the method used for defining a variable that can contain a type-tagged group of types. The type tag dataform1control is not a type, it is a type tag associated with each dataform1control in its type definition, to enable exactly this sort of functionality. For further information about type tags see the section called “Value Types, Reference Types, and Type Tags”.

Most of the types have a formnode property, which contains the reference to the dlistnode that makes the item part of the ring. Some items have a different name, and some have more than one node, so selecting the correct one is essential. For example, the form controls have a formnode and a pagenode (the dataform1option control also has a groupnode). To iterate through all the controls in the form, start with the dataform1 controls dring and use the formnode of each control to get the next one. To iterate through all the controls on a given page, use the controls property of the dataform1page and then use the pagenode of each control to get the next one. Here is an example that iterates through all pages on a form, and through each control on the page.

Example 23.2. Iterating Through the Controls on Each Page of a dataform1
function df1pagesandcontrols(dataform1 f)
  dataform1page p
  type(dataform1control) c
  string info

  info = ""
  p =@ f.pages.getfirst()
  while p !@= .nul
    if info > ""
      info = info + "{d}{a}"
    end if
    info = info + p.name + "{d}{a}" + "-" * .len(p.name) + "{d}{a}"
    c =@ p.controls.getfirst()
    while c !@= .nul
      info = info + "  " + c.name + ": type=" + c.type + "{d}{a}" 
      c =@ c.formnode.getnext()
    end while c =@= p.controls.getfirst()
    p =@ p.formnode.getnext()
  end while p =@= f.pages.getfirst()
end function info
          

In the preceding program the two iteration variables are p and c. The page variable is defined to be of one specific type: dataform1page, since that is the only type that is managed by the ring. The other is defined as type(dataform1control), since all of the various dataform1 control types will be in the ring and therefore the variable needs to be able to hold a reference to any of them.