Kbase 13349: ADM2. Frequently Asked Questions About Selection List (List Box)
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  15/10/2008 |
|
Status: Verified
GOAL:
Answers to questions frequently asked about the Progress SELECTION-LIST widget.
FACT(s) (Environment):
Progress 8.x
Progress 9.x
FIX:
How do I programmatically select certain items on the list?
The :SCREEN-VALUE attribute contains a CHARACTER Representation of the item(s) currently selected on the list.
For example, call your selection list SELECT-1 that consists of the items "RED", "GREEN", and "BLUE". If you click on "BLUE", this can be ascertained by checking SELECT-1:SCREEN-VALUE as follows:
IF SELECT-1:SCREEN-VALUE = "BLUE" THEN ...
Similarly, you can programmatically select an item in the list by setting SELECT-1:SCREEN-VALUE in the 4GL:
SELECT-1:SCREEN-VALUE = "blue".
For selection lists that allow multiple selection, :SCREEN-VALUE is a comma-delimited list of the selected items. If you select "RED" and "BLUE" on SELECT-1, it is the same as saying:
SELECT-1:SCREEN-VALUE = "red,blue".
How do I determine whether a specific item on the list has been selected?
The most direct way is to use the :IS-SELECTED()method. Use of methods requires that another variable be defined, sometimes a logical variable and sometimes a character or integer variable.
For the following example, we'll need a logical variable and we'll call it "log".
If the indicated item(s) are selected in the list, the Value of "log" is TRUE:
log = SELECT-1:IS-SELECTED("GREEN") IN FRAME f.
Similarly, if you want to check whether both "RED" and "GREEN" are selected on a multi-selection list:
log = SELECT-1:IS-SELECTED("RED,GREEN") IN FRAME f.
You can also treat the :SCREEN-VALUE like any other CHARACTER field, using string functions to test for the existence of certain items:
IF CAN-DO("GREEN", SELECT-1:SCREEN-VALUE IN FRAME f) THEN...
IF LOOKUP("GREEN", SELECT-1:SCREEN-VALUE IN FRAME f) <> 0 THEN...
How can I set the items in a selection list dynamically?
Use the various methods to place items into a list.
For example:
log = SELECT-1:ADD-FIRST("YELLOW") IN FRAME f.
This places "YELLOW" at the top of the SELECT-1 items, and gives "YELLOW","RED","GREEN","BLUE" as the complete set. You can also use the :ADD-LAST() and :INSERT() methods to make sure a new item goes into the list precisely where you want it to go.
How do I build a selection list dynamically using database fields or CHARACTER variables?
The same methods described for number (3) above can work with database fields and CHARACTER variables. For instance, if you want to build a selection list that consists of the names of all your customers:
DEF VAR log AS LOGICAL.
FOR EACH customer BY customer.name:
log = SELECT-1:ADD-LAST(customer.name) IN FRAME f.
END.
Perhaps you want to build a list based on items input by the user at runtime:
DEF VAR i AS INTEGER.
DEF VAR new-item AS CHARACTER.
DEF VAR log AS LOGICAL.
DO i = 1 TO 10:
UPDATE new-item.
log = SELECT-1:ADD-LAST(new-item) IN FRAME f.
END.
How do I programmatically make sure no item is selected in a list?
ASSIGN SELECT-1:SCREEN-VALUE = "".
How do I determine the position of a certain item in a selection list?
To find out if an item is the (i-th) item in the list, use the :LOOKUP() method as follows:
DEF VAR i AS INTEGER.
i = SELECT-1:LOOKUP("GREEN") IN FRAME f.
If the list items are "RED", "GREEN", and "BLUE" then i would be 2.
How do I determine what the "i-th" is in a selection list?
Use the :ENTRY() method to determine which item is at the (i-th) location in the list:
DEF VAR i AS INTEGER.
DEF VAR t AS CHARACTER.
i = 3.
t = SELECT-1:ENTRY(i) IN FRAME f.
In our "RED", "GREEN", "BLUE" selection list, item 3 would be "BLUE".
How do I load the selection list with the names of the fields in a particular database table?
Use the metaschema tables, whi.ch are documented in Appendix B in the Progress Version 7.3A SQL Guide and Reference.
The example below loads all of the field names for the Customer table into a selection list. Note that a character variable could also be used to indicate the choice of table:
DEF VAR x AS LOGICAL.
FIND FIRST _file WHERE _file._file-name = Customer.
FOR EACH _field OF _file:
/* Omit any hidden fields by checking for an underscore ("_") as the first character in the field name. If no "_" is detected, add the field name to the selection list. */
IF SUBSTRING(_field._field-name,1,1) <> "_" THEN
x = select-1:ADD-LAST(_field._field-name) IN FRAME frame-a.
END.
How do I create a selection list with two columns?
For this, you must use a fixed-proportion font in the Selection list. (Many MS-Windows systems default to a proportionally-spaced font so you'll have to define the selection list expressly with a fixed font.)
Once you have defined the selection list with a fixed font, use an algorithm similar to the following to load up the list:
DEF VAR pad AS CHAR.
DEF VAR i AS INTEGER.
DEF VAR stat AS LOGICAL.
FOR EACH customer:
pad = "".
DO i = 1 TO (25 - LENGTH(customer.name)):
pad = pad + " ".
END.
stat = SELECT-1:ADD-LAST(customer.name + pad + STRING(customer.cust-num)).
END.
This loop initializes a selection list with two columns, one that gives the customer name and the other, the customer number. For each customer record, it determines how many blank spaces have to be padded onto the name in order to extend it out to the column marker, which in this example is 25. It then uses the :ADD-LAST() method to add the name, padding, and cust-num (converted using the STRING function) to the selection list.
How do I create a selection list where the item selected is updated based on what I've typed into the list so far?
This is a more involved example. It requires that a trigger be written that looks at each keypress that is made. It is recommended that a fill-in field be included on the interface so that you can keep track of what has been typed in, including
deletes and backspaces.
DEF VAR x AS CHAR.
DEF VAR i AS INTEGER.
DEFINE BUTTON btn_Quit AUTO-END-KEY
LABEL "QUIT"
SIZE 9.72 BY 1.17.
/* Fill-in-2 acts as a visual cue to the user, showing what has been typed so far, including backspaces and deletes. */
DEFINE VARIABLE fill-in-2 AS CHARACTER FORMAT "X(256)":U
LABEL "Typed so far"
VIEW-AS FILL-IN NATIVE
SIZE 14 BY 1 NO-UNDO.
DEFINE VARIABLE select-1 AS CHARACTER
VIEW-AS SELECTION-LIST SINGLE SCROLLBAR-VERTICAL
LIST-ITEMS "green","blue","black","gray","orange","orangatang"
SIZE 31.57 BY 11.63 NO-UNDO.
DEFINE FRAME frame-a
fill-in-2 AT ROW 2.83 COL 28.43 COLON-ALIGNED
select-1 AT ROW 4.33 COL 18.43 NO-LABEL
btn_Quit AT ROW 19.54 COL 66.29
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT COL 1 ROW 1
SIZE 82 BY 22.
ON ANY-KEY OF select-1 IN FRAME frame-a DO:
CASE KEYFUNCTION(LASTKEY):
WHEN "DELETE-CHARACTER" THEN DO:
IF LENGTH(x) > 0 THEN DO:
x = SUBSTRING(x,1,(LENGTH(x) - 1)).
fill-in-2:SCREEN-VALUE = x.
RUN newval.
RETURN NO-APPLY.
END.
ELSE RETURN NO-APPLY.
END.
WHEN "BACKSPACE" THEN DO:
IF LENGTH(x) > 0 THEN DO:
x = SUBSTRING(x,1,(LENGTH(x) - 1)).
fill-in-2:SCREEN-VALUE = x.
RUN newval.
RETURN NO-APPLY.
END.
ELSE RETURN NO-APPLY.
E.ND.
WHEN "RETURN" THEN DO:
APPLY "ENTRY" TO btn_Quit IN FRAME frame-a.
RETURN NO-APPLY.
END.
WHEN "TAB" THEN DO:
APPLY "ENTRY" TO btn_Quit IN FRAME frame-a.
RETURN NO-APPLY.
END.
WHEN "END-ERROR" THEN DO:
/* END-ERROR */
APPLY "CHOOSE" TO btn_Quit IN FRAME frame-a.
RETURN NO-APPLY.
END.
OTHERWISE DO:
/* check for printable character */
IF KEYCODE(KEYFUNCTION(LASTKEY)) > 0 AND
KEYCODE(KEYFUNCTION(LASTKEY)) < 200
THEN DO:
x = x + KEYFUNCTION(LASTKEY).
fill-in-2:SCREEN-VALUE = x.
RUN newval.
RETURN NO-APPLY.
END.
ELSE RETURN NO-APPLY.
END.
END CASE.
END.
ENABLE select-1 fill-in-2 btn_Quit WITH FRAME frame-a.
/* Set initial value in selection list. */
select-1:SCREEN-VALUE = select-1:ENTRY(1).
WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.
PROCEDURE newval :
DEF VAR this-entry AS CHAR.
DEF VAR j AS INTEGER.
/* See if the first chars of any of the selection-list entries
matches what has been typed. If so, set the :SCREEN-VALUE to
be the entry that matches. */
DO i = 1 TO select-1:NUM-ITEMS IN FRAME frame-a:
this-entry = select-1:ENTRY(i) IN FRAME frame-a.
DO j = 1 TO LENGTH(this-entry):
IF SUBSTRING(this-entry,1,j) = x THEN
select-1:SCREEN-VALUE IN FRAME frame-a = this-entry.
END.
END.
END PROCEDURE.
How do I delete all list items from a selection list?
This can be accomplished with one line:
select-1:LIST-ITEMS = ""..