Lists are used to display an array or arrays of data. An application can display items in the list, delete items from the list, select an item or multiple items from the list, call actions on the selection, and scroll through the list. In Empress GUI Builder, two types of lists are available:
A multilist with one column is not the same as a list, although in practice, they are treated as equivalent.
The Empress GUI Builder C API offers two methods for list scrolling: automatic and user controlled. This chapter discusses both methods, the advantages of one over another and C API functions to perform automatic and user controlled scrolling with relevant examples.
With automatic scrolling, Empress GUI Builder handles the details of scrolling. All that the user's application needs to do is to store all the elements of data in the appropriate arrays. The application has to know in advance the number of items of data to be able to allocate the arrays. The main disadvantage of automatic scrolling is that the entire array has to be allocated and filled with data before any data can be displayed in the list. For large arrays, this is impractical, as large amount of memory has to be allocated for the arrays, and the scrolling is slower. The advantage of automatic scrolling is simplicity: the application does not need to be concerned with the intricate details of accessing data and passing it to C API functions at the right moment as in the case of user controlled scrolling.
Empress GUI Builder provides these two functions for automatic scrolling:
gui_status empgui_c_list_set_items (listobj, num, listval, {listval,}
(char **)0 )where:
| > object listobj | list or multilist object |
| > int num | number of elements in the listval arrays |
| > char **listval | array of strings |
gui_status empgui_c_list_set_array ( listobj, num, listvals )where:
| > object listobj | list or multilist object |
| > int num | number of elements in the arrays that make up listvals |
| > char ***listvals | array of array of strings for the columns of the list |
Both of the above functions can effectively be used for automatic scrolling. They work both for a list and a multilist. In the first function, empgui_c_list_set_items, the number of listval variables has to be known before hand while in the second function, empgui_c_list_set_array, the number of elements in the listvals array can be dynamically controlled.
Example
For an application that has a multilist called "mlist" with two columns in the main window, the variable declaration could be as follows:
object mainwin, mlistobj;
char *objname = "mlist";
gui_status status;
register int i;
char *listval1[100];
char *listval2[100];
char **listvals[3];
To get the object for this multilist:
status = empgui_c_obj_get_by_name (mainwin, objname, &mlistobj);(Assuming mainwin has already been initialized)
Allocating memory for each of the strings in listval1 array:
for (i=0; i < 100; i++)
listval1[i] = (char *) malloc(80*sizeof(unsigned char));Allocating memory for each of the strings in listval2 array:
for (i=0; i < 100; i++)
listval2[i] = (char *) malloc(80*sizeof(unsigned char));Putting data in the listval1 array:
for (i=0; i < 100; i++)
sprintf(listval1[i],"item_%d",i+1);Putting data in the listval2 array:
for (i=0; i < 100; i++)
sprintf(listval2[i],"data_%d",i+1);
/* typically, the arrays will be assigned values from a database */To set up the array listvals:
listvals[0] = (char **) listval1;
listvals[1] = (char **) listval2;
listvals[2] = (char **) 0;
The call to this function to set items in the multilist would be:
status = empgui_c_list_set_array (mlistobj, 100, listvals);
User controlled scrolling gives the application flexibility in controlling the display of data for a list and a multilist. The application does not need to allocate memory for large arrays of data. It can control the display of a list through a very small array, which would usually contain as many elements as the number of viewable rows of a list or a multilist. As the user scrolls through the list, the array needs to be updated with the right elements of data. This functionality has to be coded by the user in a scrolling function.
Empress GUI Builder provides these four functions for user controlled scrolling:
gui_status empgui_c_list_scroll_set_items (listobj, toprow, num,
numexprows, listval, { listval, } (char **) 0 )
where:
| > object listobj | list or multilist object |
| > int toprow | item number of the row to be displayed at top of the list display |
| > int num | number of rows to be displayed in the list |
| > int numexprows | total expected number of items to be displayed in the list, or 0 if unknown |
| > char **listval | array of strings |
gui_status empgui_c_list_scroll_set_array ( listobj, toprow, num,
numexprows, listvals )where:
| > object listobj | list or multilist object |
| > int toprow | item number of the row to be displayed at top of the list display |
| > int num | number of rows to be displayed in the list |
| > int numexprows | total expected number of items to be displayed in the list, or 0 if unknown |
| > char ***listvals | array of array of strings for the columns of the list |
gui_status empgui_c_list_get_num_viewrows (listobj, &num)where:
| > object listobj | list or multilist object |
| < int num | number of viewable rows in a list or multilist |
gui_status empgui_c_list_scroll_set_func (listobj, scroll_func)where:
| > object listobj | list or multilist object |
| > void (*scroll_func) | scroll function |
Example
For an application that has a multilist called "mlist" with two columns in the main window, the variable declaration could be as follows:
object mainwin, mlistobj;
char *objname = "mlist";
gui_status status;
int i;
int nviewrows;
int tn_rec;
char **listval1;
char **listval2;
char **listvals[3];
int size;
This declaration has to be global so that the scroll function can access listval1, listval2 and listvals array.
All of the code below can be part of the enter action for the module. Here, the list is set up and the scroll function is defined.
To get the object for this multilist:
status = empgui_c_obj_get_by_name (mainwin, objname, &mlistobj);(Assuming mainwin has already been initialized)
Finding the number of viewable rows in the multilist:
status = empgui_c_list_get_num_viewrows (mlistobj, &nviewrows);Number of elements in the listval1 and listval2 arrays can now be allocated depending on the number of viewable rows of the multilist:
size = ( nviewrows + 1 ) * sizeof (char **);
listval1 = (char **) malloc ( size );
listval2 = (char **) malloc ( size );
The extra element is used for null terminating the array, which is useful for freeing it up later on in the scroll function.
Assuming the data fields are less than 80 characters long, allocating memory for each of the elements in the listval1 array:
for (i=0; i < nviewrows; i++)
listval1[i] = (char *) malloc(80*sizeof(unsigned char));Allocating memory for each of the elements in the listval2 array:
for (i=0; i < nviewrows; i++)
listval2[i] = (char *) malloc(80*sizeof(unsigned char));Null terminating both arrays:
listval1[nviewrows] = (char *) 0;
listval2[nviewrows] = (char *) 0;Putting data in the listval1 array:
for (i=0; *(listval1 + i) != 0; i++)
sprintf(*(listval1 + i),"item_%d",i+1);Putting data in the listval2 array:
for (i=0; *(listval2 + i) != 0; i++)
sprintf(*(listval2 + i),"data_%d",i+1);
/* typically, the arrays will be assigned values from a database */To set up the array listvals:
listvals[0] = (char **) listval1;
listvals[1] = (char **) listval2;
listvals[2] = (char **) 0;
If an estimate of the total number of records is available, then this value is useful for Empress GUI Builder to set the size and position of the list's scroll bar properly. If the total number of records is unknown, then set the estimate to zero.
tn_rec = 100;The call to the function to set items in the multilist would be:
status = empgui_c_list_scroll_set_array (mlistobj, 1, nviewrows,
tn_rec, listvals);Initially, the top row would normally be 1. To specify which function is called when the user moves the scroll bar:
status = empgui_c_list_scroll_set_func (mlistobj, scroll_func );The scrolling function, scroll_func, would be defined as follows:
void scroll_func ( mlistobj, toprow, nrows, at_bottom )
object mlistobj;
int toprow;
int nrows;
boolean at_bottom;
These variables are passed by Empress GUI Builder to the scrolling function. toprow specifies which item number is now at top of the list display. nrows is the current number of viewable rows. at_bottom is a flag to indicate that the bottom of the list is reached. This flag is not very useful in the case of the application knowing the total number of expected elements to be displayed in the list.
{
int i;
Free the listval1 and listval2 arrays, so that they can be reallocated according to the new number of viewable rows:
for (i=0; *(listval1 + i) != 0; i++)
free ( *(listval1 + i ));
for (i=0; *(listval2 + i) != 0; i++)
free ( *(listval2 + i ));
free ( listval1 );
free ( listval2 );
Number of elements in the listval1 and listval2 arrays can now be allocated depending on the new number of viewable rows of the multilist:
size = ( nrows + 1 ) * sizeof(char **);
listval1 = (char **) malloc ( size );
listval2 = (char **) malloc ( size );
Assuming the data fields are less than 80 characters long, allocating memory for each of the elements in the listval1 array:
for (i=0; i < nrows; i++)
listval1[i] = (char
*) malloc(80*sizeof(unsigned char));
Allocating memory for each of the elements in the listval2 array:
for (i=0; i < nrows; i++)
listval2[i] = (char
*) malloc(80*sizeof(unsigned char));
Null terminating both arrays:
listval1[nrows] = (char *) 0;
listval2[nrows] = (char *) 0;
Putting data in the listval1 array:
for (i=0; *(listval1 + i) != 0; i++)
sprintf(*(listval1 +
i),"item_%d",toprow+i);
Putting data in the listval2 array
for (i=0; *(listval2 + i) != 0; i++)
sprintf(*(listval2 +
i),"data_%d",toprow+i);
This updating of listval1 and listval2 is very important. Both of these arrays need nrows records. These records are usually fetched from a database. However, fetching from the database should not start at the first record. It should start at the record whose number is specified by toprow. For the purpose of this example, these arrays will simply be assigned strings. For a detailed example, read Chapter 7 - "Example 4".
The call to the function to set items in the multilist would be:
status = empgui_c_list_scroll_set_array (mlistobj,
toprow, nrows,
tn_rec, listvals);
}