1

The javadoc of SWT CTabItem.dispose() mentioned that:

This method is not called recursively on the descendants of the receiver

What is the reason behind that? If the CTabItem is disposed, the child widgets are not displayed anymore. Why they are not disposed recursively?

Would there be any problem if I override the CTabItem.dispose() method to dispose the child widgets recursively?

Thanks

Hei
  • 70
  • 6

1 Answers1

2

That comment is actually in the JavaDoc for the Widget class which CTabItem is derived from, it applies to all controls.

When you call dispose the children of the control are destroyed, but not by calling the child controls dispose method.

The JavaDoc is telling you that overriding the dispose method won't work if you want to know when the control is disposed, instead you must listen for the SWT.Disposed event.

The code for Widget.dispose is:

public void dispose () {
    /*
    * Note:  It is valid to attempt to dispose a widget
    * more than once.  If this happens, fail silently.
    */
    if (isDisposed ()) return;
    if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
    release (true);
}

and release:

void release (boolean destroy) {
    if ((state & DISPOSE_SENT) == 0) {
        state |= DISPOSE_SENT;
        sendEvent (SWT.Dispose);
    }
    if ((state & DISPOSED) == 0) {
        releaseChildren (destroy);
    }
    if ((state & RELEASED) == 0) {
        state |= RELEASED;
        if (destroy) {
            releaseParent ();
            releaseWidget ();
            destroyWidget ();
        } else {
            releaseWidget ();
            releaseHandle ();
        }
    }
}

So it is the release method that calls releaseChildren to destroy the children.

releaseChildren for the Composite control is:

void releaseChildren (boolean destroy) {
    Control [] children = _getChildren ();
    for (int i=0; i<children.length; i++) {
        Control child = children [i];
        if (child != null && !child.isDisposed ()) {
            child.release (false);
        }
    }
    super.releaseChildren (destroy);
}

So this calls release on the child control (not dispose)

greg-449
  • 109,219
  • 232
  • 102
  • 145
  • 1
    Thanks for this informative answer. Just adding a note here. I was asking this question because the children of CTabItem are not disposed after CTabItem is disposed, which causing memory leak. As you mentioned, releaseChildren is implemented in Composite. The releaseChildren in Widget is no-op. As CTabItem is inherited from Widget not Composite, therefore the children are not disposed or destroyed. The solution to this problem is listen the SWT.Disposed event on CTabItem and dispose the control set into the CTabItem – Hei Sep 10 '14 at 10:16
  • The CTabFolder which owns the CTabItem is derived from Composite and deals with disposing of everything in the tabs. You are doing something wrong if you are getting leaks. – greg-449 Sep 10 '14 at 10:18
  • It doesn't seems to be the case. Closing a tab just dispose the CTabItem but not the control set into it. – Hei Sep 10 '14 at 10:29
  • The controls are not disposed until the CTabFolder is disposed. – greg-449 Sep 10 '14 at 10:39