Bug #8673
Deduce the logic behind OE focus management and implement in FWD
20%
Related issues
History
#1 Updated by Vladimir Tsichevski 10 days ago
- File 8376-with-focusable.p added
There is a feature related to how OE manages focus I cannot understand.
I wrote the 8376-with-focusable.p
example to learn focus-related stuff.
In this example there is a number of frames, most of them nested, which contain a number of buttons.
When I click with mouse in any frame, the first button in this frame is focused.
But there is a single exception: the frame named outerFrame
has two enabled buttons, but clicking inside this frame does not move focus to one of the frame buttons.
I am stuck, since I cannot find out, why is this frame so special.
Probably, I am missing something obvious?
The logic behind this feature should be discovered in order to be implemented in FWD.
#3 Updated by Vladimir Tsichevski 4 days ago
- Status changed from New to WIP
- % Done changed from 0 to 20
When the target is a frame, and there is no focus hint set in this frame (something roughly similar to the AbstractContainer#current
field in FWD),
OE searches for the suitable field in its field group. This is known.
The new hypothesis: the search is aborted on the first non-field item (a frame) found in the field group.
In the 8376-with-focusable.p
example the outerFrame
is enabled with the following statement:
ENABLE focusable4 focusable6 WITH FRAME outerFrame.
This way results in that the focusable4
and focusable6
buttons move to the end of the field group widgets, and the innerFrame
is the first item in the field group.
So, when the user click the outerFrame
with mouse the search for the child suitable as focus target, aborts on the innerFrame
, and the outerFrame
stays as the focus target.
#4 Updated by Vladimir Tsichevski 4 days ago
- Related to Bug #8376: Focus transfer problem with frames having no focusable contents added
#5 Updated by Vladimir Tsichevski 4 days ago
- Related to Bug #8095: LEAVE trigger fires in no focus change situation added
#6 Updated by Vladimir Tsichevski 4 days ago
- Related to Bug #7786: FOCUS handle must return only field-level widgets added
#7 Updated by Vladimir Tsichevski 4 days ago
- Related to Bug #7685: LEAVE/ENTRY events are raised before MOUSE-UP event. added
#8 Updated by Vladimir Tsichevski 4 days ago
- Related to Bug #7684: ENTRY event is emitted twice added
#9 Updated by Vladimir Tsichevski 3 days ago
- Related to Support #7339: UI - Focus added
#10 Updated by Vladimir Tsichevski 3 days ago
- Related to Bug #8711: TAB-STOP attribute wrong implementation for RECTANGLE, IMAGE and TEXT widgets added
#11 Updated by Vladimir Tsichevski 3 days ago
This comment is reserved for the emerging documentation describing the logic behind OE focus management.
It will be edited later.
#12 Updated by Vladimir Tsichevski about 21 hours ago
Question to gurus:
A Progress trigger can return a value. If the NO-APPLY
is returned, the further event processing is aborted.
The question: are values other than the NO-APPLY
ever used by Progress?
#13 Updated by Greg Shah about 19 hours ago
First, I want to record some of our older documentation:
https://proj.goldencode.com/artifacts/javadoc/latest/api/com/goldencode/p2j/ui/chui/package-summary.html#Focus_Management
https://proj.goldencode.com/artifacts/javadoc/latest/api/com/goldencode/p2j/convert/package-summary.html#Transaction_Processing_and_Block
The first reference is not 100% complete. It especially was only looked at in ChUI and the influence of mouse processing, drag and drop, multiple windows and child frames are not considered.
The second reference is based on 9.x and thus is not up to date with the additional block processing of OO, structured error handling or the more recent transaction processing related changes in 10.x and 11.x. It also doesn't consider anything related to appserver/REST/SOAP agent session processing, nor anything about persistent/super procedures.
Even with these caveats, these are useful resources.
The question: are values other than the NO-APPLY ever used by Progress?
Limiting this question to triggers, the answer is yes and no.
This may help (it is the javadoc from BlockManager.returnWorker()
):
Return from the nearest enclosing top-level block. This will process differently based on the type of the top-level block (internal/external procedures, triggers or user-defined functions), the type of return processing that is requested (see BlockManager.ReturnType) and the presence or absence of a value to return.
The following behavior is provided:
Codes Meaning ------ ----------------------------------------------------- C Invoke LogicalTerminal.consume() E Invoke TransactionManager.triggerErrorInCaller() V Invoke ControlFlowOps.setReturnValue(val) N Invoke ControlFlowOps.setReturnValue("") F Invoke setFuncReturn(val) U Invoke setFuncReturn(null) (set return value as unknown) I Invalid (compile error in Progress) Return Return Internal External Trigger Function Value Type Proc Proc -------- --------- -------- -------- ------- -------- null NORMAL N N N U non-null NORMAL V V V F null CONSUME N N NC U non-null CONSUME V V VC F null ERROR NE NE I U non-null ERROR VE VE I UIn all cases, a
ReturnUnwindException
will be thrown and this will cause the stack to unwind to the nearest enclosing top-level block. That block will then handle the return in a block specific manner. For example, in a user-defined function, the given value or by default the unknown value will be returned to the caller. Procedures and triggers have void return values.
The part about the ReturnUnwindException
is no longer 100% correct but otherwise the details are quite accurate and match the 4GL behavior. The way to interpret (for triggers) is as follows:
- A
RETURN.
("NORMAL" return without a value) in a trigger sets theRETURN-VALUE
to""
and then returns, allowing default processing to occur. - A
RETURN <expression>.
("NORMAL" return with a value) in a trigger sets theRETURN-VALUE
to the evaluated value of the<expression>
and then returns, allowing default processing to occur. - A
RETURN NO-APPLY.
("CONSUME" return without a value) in a trigger sets theRETURN-VALUE
to""
and then returns, suppressing the default processing. - A
RETURN NO-APPLY <expression>.
("CONSUME" return with a value) in a trigger sets theRETURN-VALUE
to the evaluated value of the<expression>
and then returns, suppressing the default processing. - A
RETURN ERROR.
("ERROR" return without a value) in a trigger causes a compilation error. - A
RETURN ERROR <expression>.
("ERROR" return with a value) in a trigger causes a compilation error.
So these other constructions can affect the behavior but in no case does the value actually get returned as in a function call. In the "NORMAL" return with a value and "CONSUME" return with a value, the value can only be found in RETURN-VALUE
. Relying upon this is tricky at best, because of the very idea of a trigger. It is happening in response to an event occurring, so how do you check the RETURN-VALUE
just after a trigger executes BUT BEFORE any other procedure or trigger processing overwrites the RETURN-VALUE
. Since there is just one global RETURN-VALUE
, it is a pretty poor idea to use it from a trigger, in my opinion.
I hope this helps.
Marian: If I've gotten anything wrong here, please do let us know.
#14 Updated by Vladimir Tsichevski about 17 hours ago
Thanks, Greg.
One question:
The following two RETURN <expression>.
statements look the same:
- A
RETURN <expression>.
("NORMAL" return with a value) in a trigger sets theRETURN-VALUE
to the evaluated value of the<expression>
and then returns, allowing default processing to occur.- A
RETURN <expression>.
("CONSUME" return with a value) in a trigger sets theRETURN-VALUE
to the evaluated value of the<expression>
and then returns, suppressing the default processing.
How can the "CONSUME" return with a value
be expressed in 4gl?
#15 Updated by Greg Shah about 16 hours ago
I edited it. It should have been RETURN NO-APPLY <expression>.
.