Bug #6053
Widget realisation
100%
History
#1 Updated by Marian Edu over 2 years ago
The widget 'realisation' is somehow inconsistent in FWD, there are two attributes in widget configuration with a big TODO - realized
and wasRealized
.
- the
realize
method is not always used - not all attributes that when accessed causes 'realisation' use the
canAccess
method that take care of it (with error handling) -screen-value
being one of them - some methods directly sets the
realized
flag to true whilerealize
method useswasRealized
_isRealised
uses therealised
attribute- both
realised
andwasRealised
are accessed in many places
Maybe it could be a good idea to clean this up before it grows in a larger task...
#2 Updated by Greg Shah over 2 years ago
- Assignee set to Marian Edu
- Start date deleted (
02/08/2022)
Yes, please do.
#3 Updated by Marian Edu about 2 years ago
- % Done changed from 0 to 70
- Status changed from New to WIP
#4 Updated by Marian Edu almost 2 years ago
- Status changed from WIP to Review
- File 6053.patch added
- % Done changed from 70 to 100
wasRealized
, we've made tests for widget properties that required realization or can not be changed afterwards in testcases:
- ui/fill_in/attr-force-realize.p
- ui/fill_in/attr-realized-ro.p
- ui/fill_in/attr-require-realize.p
- ui/browse/attr-realized-ro.p
- ui/combo/attr-force-realize.p
- ui/combo/attr-require-realize.p
- ui/radio_set/attr-realized-ro.p
- ui/radio_set/attr-require-realize.p
- ui/selection_list/attr-force-realize.p
- ui/selection_list/attr-realized-ro.p
- ui/selection_list/attr-require-realize.p
#5 Updated by Greg Shah almost 2 years ago
Hynek: Please review and merge if OK.
#6 Updated by Marian Edu almost 2 years ago
I think last time when we’ve tried to remove wasRealized
Roger reported some regression on <customer_app_2>
. We’ve tried to test as much as possible in <customer_app_1>
and couldn’t find any issues but maybe Roger could help with a smoke test there as well.
Thanks
#7 Updated by Hynek Cihlar almost 2 years ago
Code review 6053.patch
.
There are two references to wasRealized
causing compilation errors. I ran several test cases with these removed, assuming the simple removal was a correct resolution.
A potentially problematic place in AbstractWidget._setVisible
: container.getContentPane().normalizeZOrder();
will be not called when canAccess
will be executed for the widget for the widget. Also config.visible
won't be assigned.
Another potential issue in AbstractWidget.afterConfigUpdateBase
:
if (!c.realized && c.visible && c.visible != beforeUpdate.visible) { moveToTop(); }
If
canAccess
is executed for the widget, c.realized
will be set to true
and moveToTop
won't be called.
Another one in ComboBoxGuiImpl.updateSize
, the condition if (!config.realized)
won't be executed when canAccess
is executed for the widget.
And perhaps other similar cases as the above exist.
I'm not saying the above are real issues, just that the change will affect how the mentioned code segments will be executed. Ideally all the places where realized
is checked for false
(for the subjected widget types - combo box, radio set, selection list and perhaps browse column) should be tested.
#8 Updated by Marian Edu almost 2 years ago
Hynek Cihlar wrote:
Code review
6053.patch
.There are two references to
wasRealized
causing compilation errors. I ran several test cases with these removed, assuming the simple removal was a correct resolution.
The patch was made agains rev #13959 which was the latest one available on xfer when I've created the patch. I can't tell if simple removal was the correct solution, you might have applied the patch for frame adjustment where wasRealized
was added in the interim - in that case removal is ok since it had a check on isRealized
as well. If someone can push latest revision in xref I can recreate the patch just to be sure.
A potentially problematic place in
AbstractWidget._setVisible
:container.getContentPane().normalizeZOrder();
will be not called whencanAccess
will be executed for the widget for the widget. Alsoconfig.visible
won't be assigned.
Hynek, canAccess
is on GenericWidget
- the server-side (model) of the widget and the AbstractWidget
is - I think - the real client side implementation. The configuration seems to be passed around in both ways, if changes are done from code then it goes from GenericWidget
to AbstractWidget
and when changed from UI actions the other way around.
Let aside the fact that canAccess
was there before and there are 50+ places where it is called out of which only 3 more were added in the patch, _setVisible
is called already from setVisible
in afterConfigUpdateBase
(see you next comment) and the z-order doesn't really change unless the widget was not realized using display/enable so I have no idea why the z-order normalisation of the container's content pane is done there.
Another potential issue in
AbstractWidget.afterConfigUpdateBase
:
[...]
IfcanAccess
is executed for the widget,c.realized
will be set totrue
andmoveToTop
won't be called.
Not sure if this is possible to get in the same 'configuration update' changes for both realize
and visible
, realize
on GenericWidget
doesn't pushAttr
so maybe in this case just to be safe we can check if the widget changed from hidden to visible and was not realized before just in case realize
was changed to true in the same attributes push call.
Another one in
ComboBoxGuiImpl.updateSize
, the conditionif (!config.realized)
won't be executed whencanAccess
is executed for the widget.
I would say whatever extra processing needs to be done based on config.realized
should be done in realize
method but in this particular case the method does receive the 'before update' configuration so if need be this can be used instead to figure out if the widget was not realized before.
And perhaps other similar cases as the above exist.
I'm not saying the above are real issues, just that the change will affect how the mentioned code segments will be executed. Ideally all the places whererealized
is checked forfalse
(for the subjected widget types - combo box, radio set, selection list and perhaps browse column) should be tested.
Ideally (imho) the configuration should be make private to begin with and move everything that pertains to widget realization in the realize
method which is there to be used I guess and don't scatter realization logic all over the places, patch tape has it's use but eventually time come to clean things up :)
If you can push the latest revision to xfer I can recreate the patch today.
Thank
#9 Updated by Hynek Cihlar almost 2 years ago
Marian Edu wrote:
If you can push the latest revision to xfer I can recreate the patch today.
Will do, what's the target directory?
I'm looking at the cases I mentioned above in more detail, whether these are real issues.
#10 Updated by Marian Edu almost 2 years ago
Hynek Cihlar wrote:
Marian Edu wrote:
If you can push the latest revision to xfer I can recreate the patch today.
Will do, what's the target directory?
It's not a directory, we get that from bazaar - xfer.goldencode.com/opt/fwd/3821c/ only that I do think you guys are working on an internal development server and that one is usually ahead of xfer.
The revision I've pulled now from it is #13968, is that ok to recreate the patch?
#11 Updated by Hynek Cihlar almost 2 years ago
Marian Edu wrote:
The revision I've pulled now from it is #13968, is that ok to recreate the patch?
Yes, that is the latest of the main repository, too.
#12 Updated by Marian Edu almost 2 years ago
- File 6053.v2.patch added
Hynek Cihlar wrote:
Marian Edu wrote:
The revision I've pulled now from it is #13968, is that ok to recreate the patch?
Yes, that is the latest of the main repository, too.
Attached the new patch, did fixed the check on afterConfigUpdateBase
as there it was easy to see if the widget was realized before.
I think that there should be only one place where that realized
configuration property should be set - either GenericWidget
or AbstractWidget
should handle the realization and push that info around as needed. Right now realize
method on GenericWidget
only set that property to true but there was no real realization - the UI implementation isn't even aware the widget was marked as realized. The UI implementation does realize the widget (well, set the property to true) when the widget became visible but that is also pushed from the server-side (GenericWidget
) unless I'm missing something :(
#13 Updated by Hynek Cihlar almost 2 years ago
Marian Edu wrote:
Hynek Cihlar wrote:
Code review
6053.patch
.There are two references to
wasRealized
causing compilation errors. I ran several test cases with these removed, assuming the simple removal was a correct resolution.The patch was made agains rev #13959 which was the latest one available on xfer when I've created the patch. I can't tell if simple removal was the correct solution, you might have applied the patch for frame adjustment where
wasRealized
was added in the interim - in that case removal is ok since it had a check onisRealized
as well. If someone can push latest revision in xref I can recreate the patch just to be sure.A potentially problematic place in
AbstractWidget._setVisible
:container.getContentPane().normalizeZOrder();
will be not called whencanAccess
will be executed for the widget for the widget. Alsoconfig.visible
won't be assigned.Hynek,
canAccess
is onGenericWidget
- the server-side (model) of the widget and theAbstractWidget
is - I think - the real client side implementation. The configuration seems to be passed around in both ways, if changes are done from code then it goes fromGenericWidget
toAbstractWidget
and when changed from UI actions the other way around.
Actually currently the realized
config field is serialized only from client to server, but not from server to client. On server the field is simply assigned, but not marked to be pushed to client with setAttr
. This effectively isolates its state on client from server. I.e. on server a widget is already marked as serialized but client still sees an unrealized state. Is this intentional? If so it will be safer to keep the server state out of config and rather make it part of the server widget itself.
#15 Updated by Marian Edu almost 2 years ago
Hynek Cihlar wrote:
Actually currently the
realized
config field is serialized only from client to server, but not from server to client. On server the field is simply assigned, but not marked to be pushed to client withsetAttr
. This effectively isolates its state on client from server. I.e. on server a widget is already marked as serialized but client still sees an unrealized state. Is this intentional? If so it will be safer to keep the server state out of config and rather make it part of the server widget itself.
I don't know if this is intentional or not (do hope the question was not for me though) but the more I look at it the clear it becomes there is no need for wasRealized
attribute and not even for realized
- a widget is automatically 'realized' when placed in a field-group
, aka: frame
or dialog
. There is really no need for realize
method or anything like that, everything should be done when the frame
is set for the widget
- either statically through frame definition or dynamically by setting the frame
attribute.
So, basically if the frame
is set then the widget is fully 'realized' - the frame
is really the only requirement here.
#16 Updated by Hynek Cihlar almost 2 years ago
Marian Edu wrote:
So, basically if the
frame
is set then the widget is fully 'realized' - theframe
is really the only requirement here.
Marian, you may be right here.
Igor, do you remember the test cases for which you needed the canAccess
method and wasRealized
flag?
#17 Updated by Greg Shah almost 2 years ago
basically if the frame is set then the widget is fully 'realized' - the frame is really the only requirement here.
What about static frames (which have the frame set at compilation time)?
#18 Updated by Hynek Cihlar almost 2 years ago
Greg Shah wrote:
basically if the frame is set then the widget is fully 'realized' - the frame is really the only requirement here.
What about static frames (which have the frame set at compilation time)?
Referencing a widget attribute or method on a variable or a field (without it being part of a frame) gives a compile time error.
#19 Updated by Greg Shah almost 2 years ago
Referencing a widget attribute or method on a variable or a field (without it being part of a frame) gives a compile time error.
I think this can only happen for dynamic widgets. Static widgets in a static frame (e.g. DEF FRAME
, FORM
, DISPLAY .. WITH FRAME
...) must always know their frame. But these can be unrealized too, if I recall correctly.
#20 Updated by Marian Edu almost 2 years ago
Greg Shah wrote:
basically if the frame is set then the widget is fully 'realized' - the frame is really the only requirement here.
What about static frames (which have the frame set at compilation time)?
All attributes that require the widget to be 'realized' can be accessed without error if the widget is placed in a frame - through static frame definition. There is no difference on how the widget's parent/container is set, the errors only occurs for dynamic widget because those doesn't have the container set statically. There is no 'static widget' without a frame, a variable can only have one widget attached if present in a static frame definition.
#21 Updated by Greg Shah almost 2 years ago
There is no 'static widget' without a frame, a variable can only have one widget attached if present in a static frame definition.
There are DEF IMAGE
, DEF BUTTON
, DEF RECTANGLE
, DEF MENU
, DEF SUB-MENU
and DEF BROWSE
.
#22 Updated by Hynek Cihlar almost 2 years ago
Greg Shah wrote:
There is no 'static widget' without a frame, a variable can only have one widget attached if present in a static frame definition.
There are
DEF IMAGE
,DEF BUTTON
,DEF RECTANGLE
,DEF MENU
,DEF SUB-MENU
andDEF BROWSE
.
Even for these in 4GL a compile time error is shown when referencing widget attributes or methods with no frame assigned.
#23 Updated by Marian Edu almost 2 years ago
Greg Shah wrote:
I think this can only happen for dynamic widgets. Static widgets in a static frame (e.g.
DEF FRAME
,FORM
,DISPLAY .. WITH FRAME
...) must always know their frame. But these can be unrealized too, if I recall correctly.
Not sure what you mean by 'unrealized', once the frame
or parent
attribute is set for a widget it can not be changed not even set to unknown. Hence the funny hijack effect of display/update statements that looks like moving the widget from one frame to another.
Other than that if the widget's frame
is dynamic then when the frame is deleted the widget is not 'unrealized' and left lingering around without a parent but it is simply deleted - note the widget is also dynamic since it is not possible to place a 'static widget' in a dynamic frame because there is no such a thing as a static widget with no frame.
#24 Updated by Marian Edu almost 2 years ago
Greg Shah wrote:
There is no 'static widget' without a frame, a variable can only have one widget attached if present in a static frame definition.
There are
DEF IMAGE
,DEF BUTTON
,DEF RECTANGLE
,DEF MENU
,DEF SUB-MENU
andDEF BROWSE
.
The only exception is the MENU
that can be used as MENU-BAR
for window or POPUP-MENU
for other widgets that supports it. So this doesn't even have a frame
attribute but owner
but I expect if any attribute require this to be realized to actually mean the owner
must have been set.
#25 Updated by Hynek Cihlar almost 2 years ago
A relevant info, #6523-29.
#26 Updated by Igor Skornyakov almost 2 years ago
Hynek Cihlar wrote:
Igor, do you remember the test cases for which you needed the
canAccess
method andwasRealized
flag?
Sorry Hynek,
I do remember that I had a battle with wasRealized
flag. But it was many years ago and I've completely forgot the details.