Ask Reuben
UNBUFFERED
Why do I have to explicitly display variables after their value changes?
What is difference between buffered and unbuffered mode?
If changing to UNBUFFERED, what do I need to take into consideration?
The concept of Buffered mode is the default Informix-4gl behaviour that we inherited. It has two key characteristics … As a result of this, you would typically see code of the nature … … and … UNBUFFERED mode was introduced to tightly couple the form fields and the underlying 4gl variables. When a dialog is in unbuffered mode, you do not need to explicitly execute a DISPLAY for the new value to appear in the form. The runtime recognises when an underlying variable in an active dialog has changed and will update the display at the next user interaction. When an action is triggered in unbuffered mode, the value entered in the form field with focus is validated and copied into the underlying 4gl variable. You do not need to read the buffer. Note in the above I said that the value is validated. There is one situation where you do not want this to occur and that is with actions such as cancel, close, help etc. You do not want when that action is triggered for the runtime to say that the value is not valid and not trigger the action. Hence for those actions a new attribute validate was added and if that attribute is specified with value=no, the value remains in the buffer and is not validated and the action is triggered no matter what the value. To experiment more with buffered and unbuffered mode, I have placed some example code at the end of this article. First run the program in buffered mode, and note what happens that … Now comment out line 10 and uncomment line 11 so that we are now in UNBUFFERED mode and repeat the above series of steps There are two ways you can use unbuffered mode. For individual dialogs, you can add UNBUFFERED to the list of attributes as in that example. You can also set this mode globally with the method ui.Dialog.setDefaultUnbuffered. By transitioning to unbuffered mode you will find that you have less lines of code and your code is more intuitive. You can read more about buffered and unbuffered modes and data validation at action invocation.
INPUT BY NAME value ...
ON ACTION action
LET value = foo()
DISPLAY BY NAME value -- DISPLAY explicitly needed to display the new value in the form
INPUT BY NAME value ...
ON ACTION action INFIELD value
LET value = FGL_DIALOG_GETBUFFER() -- Need to extract the value user has typed into the field from the buffer
CALL foo(value)
#! askreuben89.4gl
MAIN
DEFINE a, b, c INTEGER
LET a = 1
LET b = 2
CLOSE WINDOW SCREEN
OPEN WINDOW w WITH FORM "askreuben89"
INPUT BY NAME a, b, c ATTRIBUTES(WITHOUT DEFAULTS = TRUE)
--INPUT BY NAME a, b, c ATTRIBUTES(WITHOUT DEFAULTS = TRUE, UNBUFFERED)
ON ACTION add1
LET c = a + b
ON ACTION add2
LET c = a + b
DISPLAY BY NAME c
ON ACTION myhelp1
MESSAGE SFMT("a=%1 buffer = %2", a, FGL_DIALOG_GETBUFFER())
ON ACTION myhelp2 ATTRIBUTES(VALIDATE = NO)
MESSAGE SFMT("a=%1 buffer = %2", a, FGL_DIALOG_GETBUFFER())
END INPUT
END MAIN
#! askreuben89.per
LAYOUT
GRID
{
a [a ]
+ b [b ]
-----
= c [c ]
}
END
END
ATTRIBUTES
a = formonly.a;
b = formonly.b;
c = formonly.c, NOENTRY;