Ask Reuben

Across then Down, Down then Across

How can I make it so that TAB goes Down then Across, rather than Across than Down?

If your form has  multiple fields arranged in two or more columns (but not using a TABLE), it maybe that you want the cursor order to move down a column, then across to the next column, rather than across the form and then down.  Before looking at a solution, I’ll just make sure you are aware of two things.

The tabbing order with Informix-4gl was determined by the order of the fields in the INPUT statement.  That is if you had INPUT BY NAME field1, field2, field3, the tabbing order is field1, field2, field3, no matter where they are positioned in the form.   In moving to a GUI environment, the users expectation is that the tabbing order would be across then down.  This could be achieved by adding OPTIONS FIELD ORDER FORM to your programs initialisation function.  Then for all dialogs, the tabbing order is across than down and is not determined by the order of the fields in the INPUT statement.

This across then down order could be overridden by use of the TABINDEX attribute in a form definition.  Using this a developer can explicitly specify the tab order in the form file.  I normally avoid the use of this attribute as it leads to a lot of form maintenance, particularly if you decide to move or add fields.  It does have one good use though in that TABINDEX=0 can be used to indicate that a field should not be included in the tab order,  a useful technique if you add dummy fields.

With OPTIONS FIELD ORDER FORM and avoiding the use of TABINDEX, there is one further piece of knowledge that you can use to down then across rather than across then down.  That is the cursor order will stay in the same container.  The example below illustrates this.

There are three parts to the example that are in a single dialog that uses OPTIONS FIELD ORDER FORM.

The first part of the form (labelled 1:)  illustrates the default behaviour.  Here we have four fields and the cursor order is across then down.

The second and third  parts add a container and the cursor order stays in the same container before moving out of the container.

The second part of the form (labelled 2:) has an HBOX with two GRID children.  The cursor order is across then down within each GRID.  So the cursor moves down within the left hand grid before going down within the right hand grid.

The third part of the form (labelled 3:) is similar but uses a GRID with Layout Tags to add two GROUPS inside a GRID.  Again the cursor moves down the left hand grid before going down the right hand grid.

The difference between the second and third part is the rendering.  The second part offers no visual clue to the user that the cursor will move down than across, this could be solved by wrapping the GRID in a GROUP.  The third part has the outline of the GROUP to reinforce the notion that the cursor stays within the GROUP before moving onto the next GROUP.

If you have a GRID where the fields are arranged in two or more columns, you can use either of these two techniques to make the cursor go down each column then across rather than going across then down or explicitly setting TABINDEX values.

#! askreuben181.4gl
MAIN
DEFINE rec RECORD
    field01 STRING,
    field02 STRING,
    field03 STRING,
    field04 STRING,
    field11 STRING,
    field12 STRING,
    field13 STRING,
    field14 STRING,
    field21 STRING,
    field22 STRING,
    field23 STRING,
    field24 STRING
END RECORD

    WHENEVER ANY ERROR STOP
    DEFER INTERRUPT
    DEFER QUIT
    OPTIONS FIELD ORDER FORM
    OPTIONS INPUT WRAP
    
    CLOSE WINDOW SCREEN
    
    OPEN WINDOW w WITH FORM "askreuben181" ATTRIBUTES(TEXT="Example")
    INPUT BY NAME rec.* ATTRIBUTES(WITHOUT DEFAULTS=TRUE)
END MAIN
#! askreuben181.per
LAYOUT
VBOX
GROUP (TEXT="1:One Grid - cursor moves across then down")
GRID
{
 [l01     ][f01      ]  [l02     ][f02      ]
 [l03     ][f03      ]  [l04     ][f04      ]
}
END
END

GROUP (TEXT="2:HBOX with two grids - cursor moves down then across")
HBOX
GRID
{
[l21     ][f21      ]
[l22     ][f22      ]
}
END
GRID
{
[l23     ][f23      ]
[l24     ][f24      ]
}
END #GRID
END #HBOX
END #GROUP

GROUP (TEXT="3:One Grid with Group Layout Tags - cursor moves down then across")
GRID
{
<G                    ><G                    > 
 [l11     ][f11      ]  [l13     ][f13      ]
 [l12     ][f12      ]  [l14     ][f14      ]
<                     ><                     >
}
END #GRID
END #GROUP

END #VBOX
END #LAYOUT
ATTRIBUTES
LABEL l01 : label01, TEXT="Field 1";
LABEL l02 : label02, TEXT="Field 2";
LABEL l03 : label03, TEXT="Field 3";
LABEL l04 : label04, TEXT="Field 4";
f01 = formonly.field01;
f02 = formonly.field02;
f03 = formonly.field03;
f04 = formonly.field04;

LABEL l11 : label1, TEXT="Field 1";
LABEL l12 : label2, TEXT="Field 2";
LABEL l13 : label3, TEXT="Field 3";
LABEL l14 : label4, TEXT="Field 4";
f11 = formonly.field11;
f12 = formonly.field12;
f13 = formonly.field13;
f14 = formonly.field14;

LABEL l21 : label21, TEXT="Field 1";
LABEL l22 : label22, TEXT="Field 2";
LABEL l23 : label23, TEXT="Field 3";
LABEL l24 : label24, TEXT="Field 4";
f21 = formonly.field21;
f22 = formonly.field22;
f23 = formonly.field23;
f24 = formonly.field24;