[Swing] SmartFields broken under certain conditions [message #1061928] |
Tue, 04 June 2013 18:50 |
|
I've come across an issue with smart fields:
If you place a smart field on a tab, hide that tab, and then re-show the tab, the smart field is broken! You cannot open the proposal form anymore, and if you type any text, each character is erased immediately.
To illustrate the problem, I created a simple test class (see attachments).
- Start the form
- Check that both smart fields are working as expected
- Press the "toggle" button (left tab disappears)
- Check that the right smart field is still ok
- Press the "toggle" button again (left tab appears)
- Check that the right smart field is still ok
- Check that the left smart field is still ok <== UNFORTUNATELY IT'S NOT!
Here is my evaluation of the problem:
- The problem is only present, when the smart field is placed on a tab. If you hide and show the field itself or a surrounding groupbox (not inside a tabbox), the smart field still works. Apparently, the problem has something to do with the tabbox behaviour. It seems that when tabs are hidden, the corresponding Swing widgets are disposed, and then re-created when the tab is visible again. The problem lies somewhere in the synchronization between the Swing widgets and the Scout model objects.
- I found that after the tab is hidden and re-shown and you click on the smart field button (the "magnifier" icon), the method org.eclipse.scout.rt.ui.swing.form.fields.smartfield.SwingScoutSmartField.showProposalPopup(ISmartFieldProposalForm) is called 2 (!) times - once for the newly created SwingScoutSmartField, once for the old one. One is "displayable", the other is not (because it has no peer attached). Because one is not displayable, the scout model object (which exist only once) is notified to close the proposal form.
- So, why are there two SwingScoutSmartField objects? Because the first one is not disconnected from Scout when it is disposed!
- Usually, this happens in org.eclipse.scout.rt.ui.swing.basic.SwingScoutComposite.P_SwingAddRemoveListener when the field is disposed. In our case, P_SwingAddRemoveListener does not get called. Why? Because the method checks for the event type HierarchyEvent.SHOWING_CHANGED. However, the removeNotify method on Component builds the event like this:
HierarchyEvent e =
new HierarchyEvent(this, HierarchyEvent.HIERARCHY_CHANGED,
this, parent,
HierarchyEvent.DISPLAYABILITY_CHANGED |
((isRecursivelyVisible())
? HierarchyEvent.SHOWING_CHANGED
: 0));
Because we set the group box for the tab to visible=false, the method isRecursivelyVisible() returns false. Therefore, the SHOWING_CHANGED type is not contained in the event!
So my proposed fix would be to change P_SwingAddRemoveListener so that it listens to HierarchyEvent.DISPLAYABILITY_CHANGED instead of HierarchyEvent.SHOWING_CHANGED.
private class P_SwingAddRemoveListener implements HierarchyListener {
@Override
public void hierarchyChanged(HierarchyEvent e) {
if (e.getID() == HierarchyEvent.HIERARCHY_CHANGED) {
if ((e.getChangeFlags() & /* >>>>> */ HierarchyEvent.DISPLAYABILITY_CHANGED /* <<<<< */ != 0) {
if (e.getComponent().isDisplayable()) {
handleSwingAddNotify();
}
else {
handleSwingRemoveNotify();
}
}
}
}
}// end private class
However, because this applies to nearly all Scout fields (because P_SwingAddRemoveListener is used by the class org.eclipse.scout.rt.ui.swing.basic.SwingScoutComposite), I would like to ask:
- Does anyone know, why the current listener listens to SHOWING_CHANGED instead of DISPLAYABILITY_CHANGED?
- Can anyone estimate the impact of the proposed fix (see above)? Would you recommend a different fix?
Thanks,
Beat
|
|
|
|
Powered by
FUDForum. Page generated in 0.03539 seconds