Skip navigation links

Package com.goldencode.p2j.ui.chui

Experimental implementations of CHARVA-based controls designed to replace Progress widgets.

See: Description

Package com.goldencode.p2j.ui.chui Description

Experimental implementations of CHARVA-based controls designed to replace Progress widgets.

Author
Eric Faulhaber
Sergiy Yevtushenko
Rohithaksha Kalluraya
Stanislav Lomany
Constantin Asofiei
Nick Saxon
Date
Sep 15, 2011
Access Control
CONFIDENTIAL

Contents

Widget data value and SCREEN-VALUE handling

Frame Width Adjustment

Insert Mode Behavior

Auto-zap Behavior

Unknown date value display

Progress Focus Management

Progress Frame Hiding Behavior

Progress Frame Hiding and PUT SCREEN output

Progress Frame Initial Display and PUT SCREEN output

READKEY in EDITING blocks

Known issues with the current design


Widget data value and SCREEN-VALUE handling

Values returned by widget when F1 is pressed right after start of the UPDATE operation.

Widget
Variable value
SCREEN-VALUE
Comments
COMBO-BOX with default variable value
(default value) (value of first choice)

COMBO-BOX with initialized variable
(initial value)
(initial value)
COMBO-BOX with variable initialized to incorrect value
(initial value) (value of first choice)
EDITOR with default variable value
(default value) (default value)
EDITOR with initialized variable
(initial value) (initial value)
FILL-IN with default variable value (default value) (default value)
FILL-IN with initialized variable (initial value) (initial value)
RADIO-SET with default variable value (value of first choice)
(value of first choice)

RADIO-SET with initialized variable (initial value) (initial value)
RADIO-SET with variable initialized to incorrect value (value of first choice) (value of first choice) Warning message:
**Attribute SCREEN-VALUE for the RADIO-SET txt1 has an invalid value of x (4058)
SELECTION-LIST with default variable value (default value) UNKNOWN

SELECTION-LIST with initialized variable (initial value) (initial value)
SELECTION-LIST with variable initialized to incorrect value (UNKNOWN value) UNKNOWN Warning message
**Attribute SCREEN-VALUE for the SELECTION-LIST txt1 has an invalid value of x. (4058)

Frame Width Adjustment

Progress 4GL adjusts leading space of the label of the widget depending on the terminal width (so the frame width). Following test cases demonstrate its behaviors.

If a frame has a "COLON" phrase defined as a part of its side-label, it will try to adjust the leading space of that side-label when the terminal width is less than the total width of the frame. In this scenario, progress throws an error but continues to show the frame with an adjustment in the leading space of the side-labels. This adjustment is possible ONLY until there is some leading space in the longest among the side-labels (in the below case its "Program Name").

For all the test cases keep the terminal width (number of columns) as 80.

  1. "frame_width_adjustment_1a.p" is a working program to demonstrate how a frame looks like without any adjustment. This fits the terminal having the width as mentioned above. To prove that Progress tries to adjust the side-label's leading space, in "frame_width_adjustment_1b.p", "name" widget's width has been increased to 64. This program shows an error message while running but on click of OK button it shows the frame with leading space being truncated. However as demonstrated in "frame_width_adjustment_1c.p", it does not truncate the text from the side-label. In that, "name" widget's length has been increased further to 65. Also note that this adjustment happens until the longest of the side-labels has a leading space. To justify this behavior, same scenario has been repeated in "frame_width_adjustment_1d.p" and "frame_width_adjustment_1e.p" with different text for "name" widget.

  2. COLON: "frame_width_adjustment_2a.p" proves its the COLON phrase which shows adjustment behavior. This program shows an error message and exits.

  3. NO-BOX: "frame_width_adjustment_3a.p" and "frame_width_adjustment_3b.p" proves that NO-BOX option does not affect the adjustment behavior. However, since NO-BOX phrase removes the frame border, two characters can be used for widgets.

  4. ATTR-SPACE and NO-ATTR-SPACE: "frame_width_adjustment_4a.p" and "frame_width_adjustment_4b.p" proves that ATTR-SPACE phrase does not affect the adjustment behavior.

  5. Leading space within the label: "frame_width_adjustment_5a.p" proves providing leading space within the label does not get adjusted when the frame width exceeds terminal width.

  6. No side-labels: "frame_width_adjustment_6a.p", "frame_width_adjustment_6b.p" and "frame_width_adjustment_6c.p" proves that side-labels does not affect the adjustment behavior.

  7. Multiple widgets of same type: "frame_width_adjustment_7a.p", "frame_width_adjustment_7b.p" and "frame_width_adjustment_7c.p" proves that longest of the side-labels are considered for adjustment. "frame_width_adjustment_7d.p", "frame_width_adjustment_7e.p" and "frame_width_adjustment_7f.p" are the similar test cases with three widgets.

  8. FILL-IN: "frame_width_adjustment_8a.p" and "frame_width_adjustment_8b.p" proves that FILL-IN phrase does not show any adjustment behavior.

  9. DOWN: "frame_width_adjustment_9a.p" and "frame_width_adjustment_9b.p" proves that DOWN phrase does not show any adjustment behavior.

  10. RETAIN x: "frame_width_adjustment_10a.p" and "frame_width_adjustment_10b.p" proves that RETAIN x phrase does not show any adjustment behavior.

  11. TO: This phrase has a different behavior than COLON behavior.

    1. "frame_width_adjustment_11a.p": Total frame width is same as terminal width. So this example runs without any error.

    2. "frame_width_adjustment_11b.p": This test case has both display and update statements separated by a pause. It shows a horizontal scroll-bar since the total frame width is more than terminal width. Notice a shift in the content when moving from display to update. Total widget width is 81 (= 65 + 12 (side-label) + 2 (frame border) + 2 (colon and space)).

    3. "frame_width_adjustment_11c.p": This program shows an error message and exits. In this case total widget width is 82 (= 66 + 12 (side-label) + 2 (frame border) + 2 (colon and space)).

    4. "frame_width_adjustment_11d.p": TO position exceeds frame width. So progress adjusts side-label by removing leading space.

    5. "frame_width_adjustment_11e.p": This program shows an error message and exits because side-label does not have enough leading space to adjust.

  1. ROW x COLUMN y:

    1. "frame_width_adjustment_12a.p" and "frame_width_adjustment_12b.p" proves that ROX x COLUMN y does not show any adjustment behavior.

    2. "frame_width_adjustment_12c.p" and "frame_width_adjustment_12d.p" proves that data part gets truncated for all the columns but last column's label does not get truncated. All other column labels get truncated if its length exceeds the width.

    3. "frame_width_adjustment_12e.p" and "frame_width_adjustment_12f.p"proves that ROX x COLUMN y with COLON-ALIGNED option does not show any adjustment behavior.

    4. "frame_width_adjustment_12g.p", "frame_width_adjustment_12h.p" and "frame_width_adjustment_12i.p" proves that ROX x COLUMN y with LEFT-ALIGNED option shows adjustment behavior ONLY if it exceeds frame width by one character.

    5. "frame_width_adjustment_12j.p" and "frame_width_adjustment_12k.p" proves that ROX x COLUMN y with RIGHT-ALIGNED option does not show any adjustment behavior.

  2. SPACE(x): "frame_width_adjustment_13a.p", "frame_width_adjustment_13b.p" and "frame_width_adjustment_13c.p": If the space value is between 1 and 73, text appears right justified (as expected). If the value is between 74 and 78, it appears left justified and for values beyond 79 and 0, it ignores the space.

Insert Mode Behavior

The following table specifies how the insert mode behaves when the focus moves between two widgets into one frame of the given types using the given transition method.

The "/" separates movements that were done due to: (TAB or ENTER or F1 to complete update) / (arrows or DISABLE current widget or WAIT-FOR FOCUS). If indicator states are the same in both cases, then "/" is omitted.


Focus Moving From

to FILLIN or BROWSE cell

to EDITOR with INSERT previously ON

to EDITOR with INSERT previously OFF

to NON-INSERT-MODE WIDGET (all others?)

FILLIN with INSERT ON

OFF / ON

ON

OFF

ON

FILLIN with INSERT OFF

OFF

ON

OFF

OFF

EDITOR with INSERT ON

OFF

ON

OFF

OFF

EDITOR with INSERT OFF

OFF

ON

OFF

OFF

NON-INSERT-MODE WIDGET (all others?)

OFF / ON|OFF *

ON

OFF

ON|OFF *

* - Depends on the state of the insert indicator when the non-insert-mode widget we are moving from is focused.

Additional rules:

  1. Transition of any kind between two browse cells makes the insert indicator OFF.

  2. If transition was initiated by a prompting statement (UPDATE/SET/PROMPT-FOR/MESSAGE UPDATE/MESSAGE SET including EDITING modifications) or a trigger call then the fill-in which will receive the focus after initial focus adjustment into this statement, will have the insert mode that was just before execution of this statement (no matter what key triggered execution of this statement). After leaving of a prompting statement/block or a trigger the insert mode is restored to the one that was just before its execution (except the case when trigger has returned NO-APPLY), and if a fill-in will receive the focus in the following focus adjustment, it will have the recently restored insert mode (no matter what key triggered leaving of this statement). When we have some nested editing blocks or triggers, the insert mode is saved before each nested call and restored after we have returned from this call. When an insert mode is restored, the insert indicator is forcedly redrawn after prompting statements, but not after triggers.

  3. Transition of any kind between any widgets (except editors), which are situated into different frames, keeps the current insert indicator state. When we leave an editor, insert indicator becomes OFF. When we enter an editor, the insert indicator is set according to the saved state of the editor.

  4. If there is no focused widget, newly displayed fillin accepts the current insert mode.

  5. On focus restoration after a WAIT-FOR cycle, if a fillin receives the focus, we should use the current insert mode for it rather the one that is stored into this fillin.

  6. The insert indicator is not cleared by HIDE ALL statement if there are not visible frames and no output has been performed using PUT SCREEN since the previous call of HIDE ALL.

  7. Rules for the insert indicator state for read-only editors:

    1. Insert indicator is always OFF when a read-only editor gains the focus. But the actual insert state is the one that was previously saved for this editor, and it will be displayed if the editor will become available for writing.

    2. Pressing INSERT key for an editor in a read-only mode will switch the displayed state to the opposite one. The saved state for this editor also will change according to the displayed state.

  8. After an APPLY "ENTRY" statement, insert state should be OFF for the ENTRY target (fill-in), or for the currently focused fill-in if ENTRY has returned NO-APPLY.

Auto-zap Behavior

The following table specifies what will be the auto-zap state when the focus moves between two widgets of the given types using the given transition method.

The "/" separates movements that were done due to: (TAB or ENTER or F1 to complete update or WAIT-FOR FOCUS) / arrows / DISABLE current widget.


Focus Moving From

to FILLIN

to BROWSE cell

FILLIN with AUTO-ZAP ON

ON / OFF / ON

ON / ON / ON

FILLIN with AUTO-ZAP OFF

ON / OFF / OFF

ON / ON / ON

OTHER WIDGETS

ON / OFF / ON

ON / ON|OFF* / ON

* - The value is ON if down or up arrow was pressed and OFF if right or left arrow was pressed.

Additional rules:

  1. Transition of any kind between two browse cells makes the auto-zap state ON.

  2. Auto-zap state becomes ON after we have tried to leave a fill-in using TAB, BACK-TAB, GO or RETURN keys, but failed because no widgets have applied ENTRY event.

  3. If we have a WAIT-FOR PAUSE cycle and a fillin receives the focus upon initial focus adjustment, then auto-zap state becomes OFF for this fillin.

  4. When the focus is restored after a trigger call (if event is not consumed, event is not VALUE-CHANGED and widget is fill-in), auto-zap state should be ON for the focused fill-in.

  5. After an APPLY "ENTRY" statement, auto-zap state should be ON for the ENTRY target (fill-in), or for the currently focused fill-in if ENTRY has returned NO-APPLY.

Unknown date value display

The following rules specify how the unknown ("?") date value is displayed - with separators (e.g. "  /  /  ") or without them (as empty string). These rules only apply to the editing mode. When a widget is disabled (or SENSITIVE is set to false), the unknown value is displayed as empty string.

  1. An unknown date (or if any value hasn't been copied to screen buffer) is displayed with separators after ENABLE / UPDATE / SET / PROMPT-FOR calls and set SENSITIVE = true, if the fill-in was in disabled state before.

  2. The following actions makes unknown date to be displayed without separators:

    • "?" key pressing;

    • CLEAR key pressing;

    • RECALL key pressing, if initial value was unknown;

    • displaying of the unknown value with enabled widget, e.g.:

      enable val with frame f.
      assign val = ?.
      display val with frame f.

Progress Focus Management

I Testcases and Raw Facts

The following table summarizes the testcases and the observed facts on the various combinations of conditions. The columns of the table are:
It is important to realize that unlike in other event-driven operating environments, Progress allows a disabled widget to be in focus.  As the result, the current focus can be in one of the following states:
The following describe search types, when searching for a widget where to place focus.

WAIT-FOR frame events without FOCUS clause
(frame events is an important part)
For UPDATE operation, Y represents the first widget in list and FY represents the frame targeted by UPDATE (Y belongs to this frame).
Testcase Focus before WAIT-FOR ENTRY trigger Initial focus in WAIT-FOR Focus after WAIT-FOR
wait-for_restore_focus1.p enabled widget X - same widget X same widget X (can get disabled by 'a trigger on 'x')
wait-for_restore_focus1e.p
wait-for_restore_focus1ef.p
enabled widget X X:NO-APPLY
there are enabled widgets
same widget X -
ignores NO-APPLY
same widget X (can get disabled by 'a trigger on 'x')
update_focus_valid0b.p update_focus_valid2b.p update_focus_valid4b.p enabled widget X Y:NO-APPLY
there are other enabled widgets
use ST5, starting from Y. enabled widget X
wait-for_restore_focus1m.p enabled widget X
X:NO-APPLY
there are only disabled widgets
same widget X -
ignores NO-APPLY
same widget X
wait-for_restore_focus1s.p enabled widget X
X:NO-APPLY
there are no other widgets
same widget X -
ignores NO-APPLY
same widget X 
update_focus_valid0.p
update_focus_valid1.p
update_focus_valid2.p
update_focus_valid3b.p
enabled widget X Y gets ENTRY, Y gets disabled widget X is set FOCUS without ENTRY. enabled widget X
update_focus_valid3.p
update_focus_valid3c.p
enabled widget X Y gets ENTRY, all widgets get disabled if no other enabled widget on screen, focus is unknown. Else, search using ST6. enabled widget X
update_focus_valid4.p enabled widget X Y:NO-APPLY
there are other enabled widgets in frame FY; all widgets in frame FY reject ENTRY.
use ST5 starting from Y; immediate exit enabled widget X
waitfor_request_valid0.p waitfor_request_valid3b.p enabled widget X Y is first enabled widget on screen. Y gets ENTRY, Y gets disabled. use ST4, starting from Y enabled widget X
waitfor_request_valid0B.p waitfor_request_valid3cB.p enabled widget X Y is NOT the first enabled widget on screen. Y gets ENTRY, Y gets disabled. first enabled widget Z in frame FY is focused, without ENTRY sent enabled widget X
waitfor_request_valid3.p enabled widget X Y gets disabled, no other enabled widgets on screen. focus is undefined enabled widget X
waitfor_request_valid3c.p enabled widget X Y gets disabled, no other enabled widgets in FY. use ST6 enabled widget X
w_valid_hidden/*A[1|2]?_[a|b]a*.p
enabled and hidden widget X - send entry to next widget in X frame same widget X
w_valid_hidden/*A[1|2]?_[a|b]b1.p
w_valid_hidden/*A[1|2]?_[a|b]b2.p
enabled widget X in hidden frame - use ST6; focus is still X before W entry same widget X
w_valid_hidden/*A[1|2]?_[a|b]c[a|b]*.p
w_valid_hidden/*A[1|2]?_[a|b]cc1.p
w_valid_hidden/*A[1|2]?_[a|b]cc2.p
enabled widget X hides widget X or parent frame use ST6; focus is still X before W entry same widget X
wait-for_restore_focus3.p undefined - first enabled widget  X last focused widget *
wait-for_restore_focus3e.p undefined X:NO-APPLY
there are enabled widgets
first enabled widget  X is attempted;
second enabled widget Y gets focus
last focused widget *
update_focus_undefined0b.p update_focus_undefined2b.p update_focus_undefined4b.p undefined Y:NO-APPLY
there are other enabled widgets
use ST5. undefined
waitfor_request_undefined0.p waitfor_request_undefined3.p waitfor_request_undefined3b.p waitfor_request_undefined3c.p undefined Y receives ENTRY and gets disabled focus is undefined, regardless if there are other enabled widgets or not. undefined
wait-for_restore_focus3t.p
wait-for_restore_focus3tf.p
undefined
all enabled widgets return NO-APPLY
there are no other enabled widgets
use ST5; immediate exit undefined
wait-for_restore_focus3m.p undefined
-
there are only disabled widgets
immediate exit undefined
wait-for_restore_focus3s.p undefined
-
there are no other widgets
immediate exit undefined
update_focus_undefined0.p update_focus_undefined1.p update_focus_undefined2.p update_focus_undefined3b.p undefined Y gets ENTRY and disabled use ST4, starting from Y. undefined
update_focus_undefined3.p update_focus_undefined3c.p undefined Y gets ENTRY, all widgets get disabled if no other enabled widget on screen, focus is unknown. Else, use ST4, starting from Y. undefined
update_focus_undefined4.p undefined Y:NO-APPLY
there are other enabled widgets in frame FY; all enabled widgets in frame FY reject ENTRY;
use ST5, from Y; immediate exit undefined
wait-for_restore_focus4.p
wait-for_restore_focus4f.p
wait-for_restore_focus4ff.p
disabled widget X - use ST2 same widget X, which remains disabled, unless enabled by a trigger
wait-for_restore_focus4e.p
wait-for_restore_focus4mf.p
wait-for_restore_focus4ef.p update_focus_invalid0b.p update_focus_invalid2b.p update_focus_invalid4b.p
disabled widget X Y:NO-APPLY
there are enabled widgets
for UPDATE operation, next enabled widget in frame FY;
else, use ST2
same widget X, which remains disabled, unless enabled by a trigger
wait-for_restore_focus4m.p disabled widget X
-
there are only disabled widgets
undefined same widget X, which remains disabled, unless enabled by a trigger
wait-for_restore_focus4s.p disabled widget X
-
there are no other widgets
undefined same widget X, which remains disabled, unless enabled by a trigger
update_focus_invalid0.p update_focus_invalid1.p update_focus_invalid2.p update_focus_invalid3b.p disabled widget X Y gets ENTRY, Y is disabled use ST4, from Y; disabled widget X
update_focus_invalid3.p update_focus_invalid3c.p disabled widget X Y gets entry, all widgets get disabled if no other enabled widget on screen, focus is unknown. Else, use ST4, from Y. disabled widget X
update_focus_invalid4.p disabled widget X Y:NO-APPLY
there are other enabled widgets in frame FY; all enabled widgets in frame FY reject ENTRY;
use ST5; immediate exit disabled widget X
WAIT-FOR frame events FOCUS Y
wait-for_restore_focus2.p enabled widget X - Y was enabled - focus set on Y same widget X (can get disabled by 'a trigger on 'x')
wait-for_restore_focus2d.p
wait-for_restore_focus2df.p
enabled widget X -
there are other enabled widgets
Y was disabled -
focus set on X - no ENTRY event sent
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus2g.p enabled widget X -
there are no other enabled widgets but X
Y was disabled -
focus set on X - no ENTRY event sent
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus2e.p enabled widget X Y:NO-APPLY
there are enabled widgets
Y is attempted;
next enabled widget Z receives ENTRY event and gets focus
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus2t.p
wait-for_restore_focus2tf.p
enabled widget X
all enabled widgets return NO-APPLY
there are no other enabled widgets
Y is attempted; next enabled widgets in the tab order are attempted; search does not wrap nor does it extend to other frames; ; immediate exit
same widget X
wait-for_restore_focus2f.p
wait-for_restore_focus2ff.p
enabled widget X Y:NO-APPLY
there are no other enabled widget but X
Y is attempted;
widget X receives LEAVE event; immediate exit
same widget X
wait-for_restore_focus2m.p
(same as 2g)
enabled widget X
X:NO-APPLY
there are only disabled widgets
focus set on X - no ENTRY event sent same widget X (can get disabled by a trigger on 'x')
waitfor_focus_request_invalid0.p
waitfor_focus_request_invalid3b.p
enabled widget X Y gets ENTRY, Y is disabled. Y = X use ST2 same widget X
waitfor_focus_request_invalid0B.p
enabled widget X Y gets ENTRY, Y is disabled. Y != X focus is set on X, without ENTRY sent same widget X
waitfor_focus_request_invalid3c.p
waitfor_focus_request_invalid3cB.p
enabled widget X Y gets ENTRY, all widgets in FY get disabled, X gets disabled use ST6 same widget X
waitfor_focus_request_invalid3.p
enabled widget X Y gets ENTRY, all widgets get disabled focus is undefined same widget X
wf_valid_A1/*A1?_[a|b]a*.p
wf_valid_A2/*A2?_[a|b]a*.p
wf_valid_A3/*A3?_[a|b]a*.p
wf_valid_A4/*A4?_[a|b]a*.p
wf_valid_A5/*A5?_[a|b]a*.p
enabled widget X Y is disabled before ENTRY no ENTRY is sent to Y. X receives focus without ENTRY same widget X
wf_valid_A1/*A1?_[a|b]b[a|c]*.p
wf_valid_A4/*A4?_[a|b]b[a|c]*.p
wf_valid_A1/*A1?_[a|b]bb*.p
wf_valid_A4/*A4?_[a|b]bb*.p
enabled widget X ENTRY disables Y X and Y in same frame. if X is still enabled, X is focused without ENTRY. else, use ST6. same widget X
wf_valid_A2/*A2?_[a|b][a|c]*.p
wf_valid_A3/*A3?_[a|b][a|c]*.p
wf_valid_A5/*A5?_[a|b][a|c]*.p
enabled widget X ENTRY disables Y X and Y in different frames. X is still enabled, focus is set to undefined. same widget X
wf_valid_A2/*A2?_[a|b]bb*.p
wf_valid_A3/*A3?_[a|b]bb*.p
wf_valid_A5/*A5?_[a|b]bb*.p
enabled widget X ENTRY disables Y X and Y in different frames. X is disabled, use ST6. same widget X
wf_valid_A1/*A1a_c[a|b][a|b].p
wf_valid_A2/*A2a_c[a|b][a|b]*.p
wf_valid_A3/*A3a_c[a|b][a|b]*.p
wf_valid_A4/*A4a_c[a|b][a|b]*.p
wf_valid_A5/*A5a_c[a|b][a|b]*.p
enabled widget X ENTRY for Y returns NO-APPLY use ST5. same widget X
wf_valid_A1/*A1a_c[a|b]c*.p
wf_valid_A4/*A4a_c[a|b]c*.p
enabled widget X all widgets return NO-APPLY X and Y in same frame. if X is not reached, wait-for ends. if X is reached, it ignores no-apply. same widget X
wf_valid_A2/*A2a_c[a|b]c*.p
wf_valid_A3/*A3a_c[a|b]c*.p
wf_valid_A5/*A5a_c[a|b]c*.p
enabled widget X all widgets return NO-APPLY X and Y in different frames. X is focused without ENTRY. same widget X
wait-for_restore_focus5.p undefined - Y was enabled - focus set on Y
If Y is not the first enabled widget X, X gets ENTRY event before Y without LEAVE event.
last focused widget *
wait-for_restore_focus5d.p
wait-for_restore_focus5t.p
undefined - Y was disabled - use ST6 last focused widget *
wait-for_restore_focus5g.p undefined
-
there are only disabled widgets
Y was disabled - focus is undefined last focused widget *
wait-for_restore_focus5e.p undefined
Y:NO-APPLY
there are enabled widgets
If Y is not the first enabled widget X in the first displayed frame, X gets ENTRY event.
Then Y gets ENTRY and the next enabled widget X finally gets ENTRY and remains focused
last focused widget *
wait-for_restore_focus5ee.p undefined
all enabled widgets return NO-APPLY
there are no other enabled widgets
If Y is not the first enabled widget X in the first displayed frame, X gets ENTRY event.
Then Y gets ENTRY and all next enabled widgets in the tab order (no wrap).
X receives LEAVE event; immediate exit
X
wait-for_restore_focus5m.p undefined Y:NO-APPLY
there are only disabled widgets
Y - ignores NO-APPLY
last focused widget *
wait-for_restore_focus5s.p undefined Y:NO-APPLY
there are no other widgets
Y - ignores NO-APPLY Y
waitfor_focus_request_undefined0.p waitfor_focus_request_undefined3b.p undefined Y is the first enabled widget on screen; Y gets disabled use ST4, starting from Y. last focused widget
waitfor_focus_request_undefined3.p waitfor_focus_request_undefined3c.p undefined Y is the first enabled widget on screen; Y gets disabled; no other enabled widgets focus is undefined undefined
waitfor_focus_request_undefined0B.p waitfor_focus_request_undefined3cB.p undefined Y is NOT the first enabled widget on screen; Y gets disabled focus is undefined, regardless if there are other enabled widgets on screen. undefined
wf_undefined_A1/*A1?_[a|b]a.p wf_undefined_A2/*A2?_[a|b]a.p undefined - focus is set on first enabled widget on screen W if Y is disabled before ENTRY or Y = W. ENTRY is not sent to W last focused widget
wf_undefined_A1/*A1?_[a|b][a|b]*.p undefined Y gets disabled Y frame is the first enabled frame on screen; use ST6 last focused widget
wf_undefined_A2/*A2?_[a|b]c[a|c]*.p undefined Y gets disabled Y frame is not the first enabled frame on screen; W is still enabled; focus is undefined last focused widget
wf_undefined_A2/*A2?_[a|b]cb*.p undefined Y gets disabled Y frame is not the first enabled frame on screen; W is disabled or hidden; use ST6 last focused widget
wait-for_restore_focus6.p disabled widget X - Y was enabled - focus set on Y
same widget X
wait-for_restore_focus6d.p
wait-for_restore_focus6f.p
wait-for_restore_focus6f2.p
wait-for_restore_focus6f3.p
wait-for_restore_focus6f4.p
wait-for_restore_focus6f5.p waitfor_focus_request0.p waitfor_focus_request3.p waitfor_focus_request3b.p waitfor_focus_request3c.p
disabled widget X - Y was disabled -
use ST4 starting from Y
same widget X (can get enabled by a trigger on 'x')
wait-for_restore_focus6g.p disabled widget X
-
there are only disabled widgets
Y was disabled - focus is undefined
same widget X
wait-for_restore_focus6e.p disabled widget X
Y:NO-APPLY
there are enabled widgets
Y is attempted; next enabled widget in tab order gets focus same widget X
wait-for_restore_focus6e2.p disabled widget X
Y:NO-APPLY
next enabled widgets NO-APPLY
Y is attempted; next enabled widget in tab order are attempted; immediate exit same widget X
wait-for_restore_focus6m.p disabled widget X -
there are only disabled widgets
undefined same widget X
wait-for_restore_focus6s.p disabled widget X
-
there are no other widgets
undefined same widget X
waitfor_focus_request0B.p waitfor_focus_request03cB.p disabled widget X Y receives ENTRY; Y gets disabled use ST4 starting from Y same widget X
wf_invalid_A1/*A1?_[a|b]a*.p wf_invalid_A2/*A2?_[a|b]a*.p wf_invalid_A3/*A3?_[a|b]a*.p wf_invalid_A4/*A4?_[a|b]a*.p wf_invalid_A5/*A5?_[a|b]a*.p disabled widget X - use ST6. same widget X
wf_invalid_A1/*A1?_[a|b]b*.p wf_invalid_A4/*A4?_[a|b]b*.p disabled widget X Y gets disabled Y and X in same frame. use ST6. same widget X
wf_invalid_A2/*A2?_[a|b]b*.p wf_invalid_A3/*A3?_[a|b]b*.p wf_invalid_A5/*A5?_[a|b]b*.p disabled widget X Y gets disabled Y and X in different frames. focus is undefined. same widget X
WAIT-FOR window events without FOCUS clause
Testcase Focus before WAIT-FOR ENTRY trigger Initial focus in WAIT-FOR Focus after WAIT-FOR
wait-for_restore_focus7.p enabled widget X - same widget X same widget X (can get disabled by 'a trigger on 'x')
wait-for_restore_focus7e.p
wait-for_restore_focus7ef.p
enabled widget X
X:NO-APPLY
there are enabled widgets
same widget X -
ignores NO-APPLY
same widget X (can get disabled by 'a trigger on 'x')
wait-for_restore_focus7m.p enabled widget X
X:NO-APPLY
there are only disabled widgets
same widget X -
ignores NO-APPLY
same widget X
wait-for_restore_focus7s.p enabled widget X
X:NO-APPLY
there are no other widgets
same widget X -
ignores NO-APPLY
same widget X
wait-for_restore_focus8.p undefined - first enabled widget  X last focused widget *
wait-for_restore_focus8e.p undefined X:NO-APPLY
there are enabled widgets
first enabled widget  X is attempted;
second enabled widget Y gets focus
last focused widget *
wait-for_restore_focus8t.p
wait-for_restore_focus8tf.p
undefined all enabled widgets return NO-APPLY
there are no other enabled widgets
all enabled widgets are attempted in the tab order; search does not extend to the next frame; focus undefined undefined
wait-for_restore_focus8m.p undefined -
there are only disabled widgets
undefined undefined
wait-for_restore_focus8s.p undefined -
there are no other widgets
undefined undefined
wait-for_restore_focus9.p
wait-for_restore_focus9f.p
wait-for_restore_focus9ff.p
disabled widget X - next enabled widget Y in the tab order of the frame containing X; the search does wrap; continues on the first displayed frame - no ENTRY event sent same widget X, which remains disabled, unless enabled by a trigger
wait-for_restore_focus9e.p
wait-for_restore_focus9mf.p
wait-for_restore_focus9ef.p
disabled widget X Y:NO-APPLY
there are enabled widgets
next enabled widget Y in the tab order of the frame containing X; the search does wrap; continues on the first displayed frame; continues through all displayed frames - no ENTRY event sent same widget X, which remains disabled, unless enabled by a trigger
wait-for_restore_focus9m.p disabled widget X
-
there are only disabled widgets
undefined same widget X
wait-for_restore_focus9s.p disabled widget X
-
there are no other widgets
undefined same widget X
WAIT-FOR window events FOCUS Y
wait-for_restore_focus10.p enabled widget X - Y was enabled - focus set on Y same widget X (can get disabled by 'a trigger on 'x')
wait-for_restore_focus10d.p enabled widget X - Y was disabled -
focus set on next enabled widget Z - no ENTRY event sent
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus10g.p enabled widget X
-
there are no other enabled widgets but X
Y was disabled -
focus set on X - no ENTRY event sent
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus10e.p enabled widget X
Y:NO-APPLY
there are enabled widgets
Y is attempted;
next enabled widget Z receives ENTRY event and gets focus
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus10f.p
wait-for_restore_focus10ff.p
enabled widget X
Y:NO-APPLY
there are no other enabled widget but X
Y is attempted;
focus set on X  - no ENTRY event sent
same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus10m.p
(same as 10g)
enabled widget X
X:NO-APPLY
there are only disabled widgets
focus set on X - no ENTRY event sent same widget X (can get disabled by a trigger on 'x')
wait-for_restore_focus11.p undefined - Y was enabled - focus set on Y
If Y is not the first enabled widget X, X gets ENTRY event before Y without LEAVE event.
last focused widget *
wait-for_restore_focus11d.p undefined - Y was disabled - focus set on first enabled widget Z among all displayed frames last focused widget *
wait-for_restore_focus11g.p undefined
-
there are only disabled widgets
Y was disabled - focus is undefined last focused widget *
wait-for_restore_focus11e.p undefined
Y:NO-APPLY
there are enabled widgets
If Y is not the first enabled widget X, X gets ENTRY event before Y without LEAVE event.
Then Y gets ENTRY and the next enabled widget X finally gets ENTRY and remains focused
last focused widget *
wait-for_restore_focus11ee.p undefined
Y:NO-APPLY
next enabled widgets NO-APPLY

last focused widget *
wait-for_restore_focus11ea.p
wait-for_restore_focus11eb.p
wait-for_restore_focus11ec.p
undefined
Y:NO-APPLY
next enabled widgets NO-APPLY

last focused widget *
wait-for_restore_focus11m.p undefined Y:NO-APPLY
there are only disabled widgets
Y - ignores NO-APPLY last focused widget *
wait-for_restore_focus11s.p undefined Y:NO-APPLY
there are no other widgets
Y - ignores NO-APPLY Y
wait-for_restore_focus12.p disabled widget X - Y was enabled - focus set on Y same widget X
wait-for_restore_focus12d.p
wait-for_restore_focus12f.p
wait-for_restore_focus12f2.p
wait-for_restore_focus12f3.p
wait-for_restore_focus12f4.p
wait-for_restore_focus12f5.p
disabled widget X - Y was disabled -
focus set on next enabled widget Z - no ENTRY event sent
same widget X (can get enabled by a trigger on 'x')
wait-for_restore_focus12g.p disabled widget X
-
there are only disabled widgets
Y was disabled - focus is undefined same widget X
wait-for_restore_focus12e.p disabled widget X Y:NO-APPLY
there are enabled widgets
Y is attempted; next enabled widget in tab order gets focus same widget X
wait-for_restore_focus12e2.p disabled widget X
Y:NO-APPLY
next enabled widgets NO-APPLY
Y is attempted; next enabled widget in tab order are attempted; Y gets focus - ignores NO-APPLY same widget X
wait-for_restore_focus12m.p disabled widget X -
there are only disabled widgets
undefined same widget X
wait-for_restore_focus12s.p disabled widget X
-
there are no other widgets
undefined same widget X (can get enabled by a trigger on 'x')

II Conclusions

  1. Focus is managed in scopes. A focus scope has the lifetime of a single WAIT-FOR event processing loop, either coded directly as an explicit WAIT-FOR statement, or through other high level terminal input/output statements. Scopes get nested when a trigger or a HELP application is invoked that performs another WAIT-FOR operation.
  2. Creation of a new focus scope preserves the existing scope's focus information. New scope then establishes its own focus. This change is not accompanied with the usual LEAVE event, however. The rules for this initial focus setting are described later.
  3. While in the event processing loop, the focus is checked after application of every event. The purpose of this check is to detect a situation where the focus needs to be adjusted forcibly. There is only one such a situation: the current focus is either undefined or invalid before applying the event, and the application of the event has made available at least one focusable widget. In this case the first focusable widget in the tab order for the active frame gets the focus without receiving ENTRY event so no triggers are involved. However, if the available widgets belong to another frame or frames, the activate frame is switched and the focus is set on the first widget in the tab order of the new active frame. The first displayed frame becomes the new active frame. This focus adjustment won't be active if the initial focus on entry to WAIT-FOR was rejected by triggers for all enabled widgets.
  4. When WAIT-FOR exits the loop, it destroys the focus scope and restores the focus for the previous scope. However, no ENTRY event is applied to the focused widget. In some cases, the resulting focus differs from the original. The rules for restoring the focus are described later.
  5. When trying to adjust focus (with or without ENTRY) to a widget, the widget must be ENABLED and both parent frame and widget must be VISIBLE.
  6. If ENTRY triggered by a navigation key returns no-apply, then focus must be searched (sending ENTRY) within widgets in tab-order after current focus, without wrapping. If no widget accepts ENTRY, then focus remains on the original widget.

Depending on the current focus state and whether the focus is specified explicitly in WAIT-FOR or is implicitly assumed, the following sections describe the rules for the initial focus on entry to the event processing loop and the final focus when WAIT-FOR completes. Initial focus on entry is also affected by a trigger defined for the ENTRY event, if such a trigger exists and performs RETURN NO-APPLY.


Valid focus on X, implicit focus in WAIT-FOR:
Undefined focus, implicit focus in WAIT-FOR:

Invalid focus on X, implicit focus in WAIT-FOR:

Valid focus on X, explicit focus on Y in WAIT-FOR (in UPDATE case, Y is first widget in list):

Undefined focus, explicit focus on Y in WAIT-FOR (in UPDATE case, Y is first widget in list):

Invalid focus on X, explicit focus on Y in WAIT-FOR (in UPDATE case, Y is first widget in list):


When UPDATE or WAIT-FOR is used, the following describes the behavior when a trigger for LEAVE event is used:
Nested UPDATE or WAIT-FOR

Frame-level ENTRY/LEAVE and NEXT-FRAME behavior

X - current focus, triggers are applied to this widget
X2 - first enabled widget in FX after X, in tab-order
Y - first widget in UPDATE or the explicit widget in WAIT-FOR ... FOCUS Y
FX - parent frame for X, X2, Y
FZ - the next frame on screen which has an enabled widget Z
T - trigger on a key (i.e. not a ENTRY/LEAVE trigger)
Frame ENTRY/LEAVE rules ON .... NEXT-FRAME APPLY "NEXT-FRAME"

III New Facts

The set of testcases apply_entry*.p shows some other details of ENTRY behavior; assume X receives ENTRY via APPLY "ENTRY" and there is an ON ENTRY trigger for it:

The MESSAGE ... UPDATE statement adjusts focus after it has been executed this way (see msg_entry*.p)

The set of testcases focus_apply*.p uncovers some details of the APPLY statement regarding the focus management:

Before reading the focus adjustment prior to trigger invocation rules, the following info must be noted:

The pending widget will be set on focus by APPLY, before trigger invocation, if the following conditions are met: The following are the restoration rules, after trigger invocation:

Progress Frame Hiding Behavior

General description

Frame hiding in Progress 4GL can be split into three large classes depending on the basic cause:

  1. Explicit application requests.
  2. Implicit frame hiding triggered by frame placement.
  3. Implicit frame hiding triggered by loops scope-related rules.
Explicit application requests.

Explicit application requests are triggered by HIDE or HIDE ALL statements in 4GL code.

Implicit frame hiding triggered by frame placement.

Implicit frame hiding triggered by frame placement takes place in two situations:

  1. When screen is occupied with other frames and there is not enough vertical space to place another non-overlay frame which has no explicitly specified row
  2. When space required for non-overlay frame with explicitly specified row is occupied with other frame.
In either case this hiding mechanism is invoked only when frame is switched from hidden to visible state during explicit or implicit VIEW call. This mechanism has only geometrical rules (only frames required to free up required space are get hidden) and not related to frame life-time cycle or other such things.
Implicit frame hiding triggered by loops scope-related rules.
This type of frame hiding is completely controlled by frame life cycle and its interaction with loop blocks. There are two basic parts of this frame hiding mechanism: marking of frames for hiding and triggering of hiding the hiding.

The general rule for marking frame for hiding is that frames are marked for hiding when block to which frame is scoped or some outer block is retried or iterated. When iterated or retried block to which frame is scoped, frame is marked for hiding immediately ("immediately" here means that frame will be marked during next client call). Iteration of outer block means exit from block to which frame is scoped. During block exit frames registered at current scope are moved to outer scope for further processing. In outer scope frames moved from inner scope are marked for hiding during next iteration/retry processing. Note that frames moved from inner scope are marked only once. Note that for some types of blocks abnormal exit from the block caused by ENDKEY or ERROR condition causes also resetting of marking for hiding.

General rule for triggering of the frame hiding is that it happens on first explicit or implicit VIEW call for the frame which belongs to current scope on second or subsequent iterations of this or outer looping block. But this rule has several exceptions so actual rules will be simpler to describe in terms of implementation. The general rule in this case can be described so:

This approach guarantees that first VIEW call which will happen inside current or any inner block will trigger hiding. It also prevents triggering of hiding more than once for frames scoped to current and outer blocks by VIEW call in current and inner blocks.

As mentioned above general rule has exceptions:

Note that all these exceptions do not affect frames in current block and VIEW for these frames still triggers pausing. This effect is illustrated by frame06.p .

Progress Frame Hiding and PUT SCREEN output

Progress frame hiding affects the PUT SCREEN output. There are two distinct cases:
The rules Progress follows are derived from a set of testcases named frame_hiding_clears_put_screen*.p.

  1. Explicit and implicit frame hiding behave the same way with regards to the PUT SCREEN output. With the implicit hiding, the frame being hidden behaves as it is not on top of the Z-order, which simply means that the frame causing hiding is considered to be on top.
  2. PUT SCREEN output that has landed within the frame's rectangle gets cleared unconditionally.
  3. Any existing PUT SCREEN output located above or below the frame is not affected.
  4. Any existing PUT SCREEN output located to the left of the frame, being it the result of one or more PUT SCREEN statements, crossing the frame rectangle or not, remains on the screen even if a part of it has landed within the frame rectangle and gets cleared.
  5. A frame being hidden from the top of the Z-order may affect also the PUT SCREEN output that has landed to the right of the frame's rectangle, if the following conditions are met:

Progress Frame Initial Display and PUT SCREEN output

Progress frame initial display may affect the PUT SCREEN output.
During initial display some areas of new frame are refreshed unconditionally and some may be refreshed depending on the conditions. Unconditionally refreshed parts of frame are border corners, if frame does not have NO-BOX option and top edge of the frame border, if frame has title. Entire frame area, including borders, is refreshed if frame intersects other frame which was the top frame in Z-order at the moment when this frame is displayed first time. 

READKEY in EDITING blocks

When CHOOSE event can be triggered (i.e. a BUTTON is in focus), the READKEY will: When other widget is in focus, with a type different then BUTTON, then READKEY called editing loop will not fire any events like VALUE-CHANGED, ENTRY, LEAVE or any-key.

When READKEY is used outside EDITING block, no events will be fired.

Known issues with the current design

Existing design was initially based on CHARVA library and inherited event queue/listener model (which, in turn, resembles AWT/Swing event model). Event based approach is not directly applicable to 4GL event model which is synchronous while CHARVA/AWT/Swing event model is asynchronous. In order to overcome these differences P2J uses mixed approach - events are still placed in event queue, but processing of these events is performed in synchronous way. Also, in order to implement 4GL-specific behavior stacked event queues were introduced. In each moment of time only one queue is active, but runtime may create new empty event queue, perform some tasks, process messages and then drop it and restore active event queue. In regard to event which was processed at the moment of switching queue all this processing is performed as single atomic operation similar to regular function call. This feature closely resembles 4GL behavior when some event may invoke trigger which in turn may perform some event processing (start event processing loop, invoke APPLY, etc.), but from point of view of event which caused trigger invocation all these operations are performed synchronously.

Nevertheless, despite its flexibility resulting UI package design is complex and interaction of different components of the package is far from obvious despite the fact that wast majority of required functionality does not require such a complex design. Also, this complexity complicates support, maintenance and further development of the UI package.

During discussion about possible refactoring of the existing code and approaches which may simplify design, following issues were found:

  1. It is possible to eliminate some event listeners, in particular ItemListener and ActionListener.
  2. Some listeners are hard to eliminate because there is no direct relationship between interacting parts. For example, ComboBox implements SelectionListener and watches for selection events, but event is sent from SelectionListModel. SelectionListModel knows nothing about ComboBox as well as ComboBox knows nothing about SelectionListModel. Fortunately these listeners and this kind of interaction is not related to event queue and does not depend on it, so these event listeners can be left as is without negative impact on the architecture.
  3. In several places components post events into the event queue and this is used as asynchronous call to other component. There are two kinds of such event queue usage:
    1. "trailing calls", when new event is posted and processing of the current event is immediately finished. This kind of usage is heavily used by Browse, for example - from many locations fireValueChanged() method is invoked which posts a message and almost immediately exits (there are also other code after posting message, but I think it can be safely reordered).
    2. "post event and do something", when event is posted but processing continues, and processing may include posting of other messages as well. For example, for printable characters FillIn posts message and only then does other processing, including posting of another messages.
    First kind of event posting can be avoided in rather simple way - just allow event processing method return value (new event to process). By allowing returning list of events second kind of event posts can be avoided too. Nevertheless this does not solve problem completely, just event queue will not be exposed and will remain hidden inside event processing method.
  4. Heavy usage of nested event queues described above. Since nested queues reflect 4GL behavior they will be hard to avoid. The approach mentioned for #3 (list of events returned from event processing method) will work for nested queues too, but, again, this not eliminates event queue, just makes it hidden.


Copyright (c) 2005-2011, Golden Code Development Corporation.
ALL RIGHTS RESERVED. Use is subject to license terms.
Skip navigation links
Copyright (c) 2004-2017, Golden Code Development Corporation.
ALL RIGHTS RESERVED. Use is subject to license terms.