DoGetBestSize not called in 2.9.2.4

Hi All,

I came across a strange behaviour while looking at the multi-line text capabilities of UltimateListCtrl, and basically the way DoGetBestSize is handled. Cutting the story short, in ULC I create the list control header explicitly passing a non-default “size” parameter to the header window (which is a subclass of wx.PyControl).

Using wxPython 2.8.11.0 on Windows Vista/7, the DoGetBestSize method for the header control is correctly called and the header window is correctly sized. Using 2.9.2.4, the DoGetBestSize method is never called, so the window gets messed up. The only way I found out to actually get that method executed is to remove the “size” parameter (or to give a wx.DefaultSize value to it) while constructing the header window.

The attached sample reproduces the problem for me. If you run it with 2.8, youll see the wx.TextCtrl populated with messages sent by the wx.PyControl. If you use 2.9, no message will appear.

I believe it to be a bug in 2.9, as passing a non-default “size” argument to a wx.PyControl does not necessarily mean “forget about calculating the best size for this control”. Its just a guess or a default value for some situations.

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”
http://xoomer.alice.it/infinity77/

import PyQt4.QtGui

Traceback (most recent call last):

File “”, line 1, in

ImportError: No module named PyQt4.QtGui

import pygtk

Traceback (most recent call last):

File “”, line 1, in

ImportError: No module named pygtk

dgbs_bug.py (4.04 KB)

···

import wx

It looks like at least part of the difference is that in 2.9 the minsize is being set to the size passed in to the constructor like it does for other control classes. In 2.8 it doesn't do that for wx.Control, just for the actual widget controls. If both components of the minsize are set to non-devault values then GetBestSize will not be called from GetEffectiveMinSize, which is the method used by sizers.

wxSize wxWindowBase::GetEffectiveMinSize() const
{
     // merge the best size with the min size, giving priority to the min size
     wxSize min = GetMinSize();

     if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
     {
         wxSize best = GetBestSize();
         if (min.x == wxDefaultCoord) min.x = best.x;
         if (min.y == wxDefaultCoord) min.y = best.y;
     }

     return min;
}

···

On 10/31/11 3:43 AM, Andrea Gavana wrote:

Hi All,

     I came across a strange behaviour while looking at the multi-line
text capabilities of UltimateListCtrl, and basically the way
DoGetBestSize is handled. Cutting the story short, in ULC I create the
list control header explicitly passing a non-default "size" parameter to
the header window (which is a subclass of wx.PyControl).

Using wxPython 2.8.11.0 on Windows Vista/7, the DoGetBestSize method for
the header control is correctly called and the header window is
correctly sized. Using 2.9.2.4, the DoGetBestSize method is *never*
called, so the window gets messed up. The only way I found out to
actually get that method executed is to remove the "size" parameter (or
to give a wx.DefaultSize value to it) while constructing the header window.

The attached sample reproduces the problem for me. If you run it with
2.8, youll see the wx.TextCtrl populated with messages sent by the
wx.PyControl. If you use 2.9, no message will appear.

I believe it to be a bug in 2.9, as passing a non-default "size"
argument to a wx.PyControl does not necessarily mean "forget about
calculating the best size for this control". Its just a guess or a
default value for some situations.

--
Robin Dunn
Software Craftsman

Hi Robin,

···

On 31 October 2011 21:09, Robin Dunn wrote:

On 10/31/11 3:43 AM, Andrea Gavana wrote:

Hi All,

 I came across a strange behaviour while looking at the multi-line

text capabilities of UltimateListCtrl, and basically the way

DoGetBestSize is handled. Cutting the story short, in ULC I create the

list control header explicitly passing a non-default “size” parameter to

the header window (which is a subclass of wx.PyControl).

Using wxPython 2.8.11.0 on Windows Vista/7, the DoGetBestSize method for

the header control is correctly called and the header window is

correctly sized. Using 2.9.2.4, the DoGetBestSize method is never

called, so the window gets messed up. The only way I found out to

actually get that method executed is to remove the “size” parameter (or

to give a wx.DefaultSize value to it) while constructing the header window.

The attached sample reproduces the problem for me. If you run it with

2.8, youll see the wx.TextCtrl populated with messages sent by the

wx.PyControl. If you use 2.9, no message will appear.

I believe it to be a bug in 2.9, as passing a non-default “size”

argument to a wx.PyControl does not necessarily mean "forget about

calculating the best size for this control". Its just a guess or a

default value for some situations.

It looks like at least part of the difference is that in 2.9 the minsize is being set to the size passed in to the constructor like it does for other control classes. In 2.8 it doesn’t do that for wx.Control, just for the actual widget controls. If both components of the minsize are set to non-devault values then GetBestSize will not be called from GetEffectiveMinSize, which is the method used by sizers.

wxSize wxWindowBase::GetEffectiveMinSize() const

{

// merge the best size with the min size, giving priority to the min size

wxSize min = GetMinSize();



if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)

{

    wxSize best = GetBestSize();

    if (min.x == wxDefaultCoord) min.x =  best.x;

    if (min.y == wxDefaultCoord) min.y =  best.y;

}



return min;

}

Thank you for that, I guess then the obvious thing to do is not to pass any size parameter for custom controls (if I want to get DoGetBestSize executed, I mean). I’ll see if I can get any other strange behaviour for the other AGW widgets.

On a completely unrelated note, I am still getting assertion errors from the AUI (wx.lib.agw one) demo, as per attached screenshot. How do I debug these? How can I find where the offending line is? It’s curious as other apps I have work OK with the latest AGW from SVN, but the demo asserts when I close the main frame…

Thank you.

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”
http://xoomer.alice.it/infinity77/

On a completely unrelated note, I am still getting assertion errors from
the AUI (wx.lib.agw one) demo, as per attached screenshot. How do I
debug these? How can I find where the offending line is? It's curious as
other apps I have work OK with the latest AGW from SVN, but the demo
asserts when I close the main frame...

Running this in the WIT with the demo's AuiFrame selected:

  >>> for c in [obj] + list(obj.Children):
  ... if c is not c.GetEventHandler():
  ... print c.__class__.__name__, ' has handler ', c.GetEventHandler().__class__.__name__
  ...

gives me this:

AuiFrame has handler AuiManager
AuiNotebook has handler AuiManager
Grid has handler EvtHandler
HtmlWindow has handler EvtHandler
AuiNotebook has handler AuiManager
AuiFloatingFrame has handler AuiManager

We can ignore the Grid and HtmlWindow items since they can be expected to clean up after themselves. Are any of the remaining windows calling AuiManager.UnInit so the manager will remove itself from the managed frame's EventHandler stack? Perhaps we should find a way to do that automatically...

···

On 10/31/11 2:17 PM, Andrea Gavana wrote:

--
Robin Dunn
Software Craftsman

Hi Robin,

···

On 1 November 2011 03:30, Robin Dunn wrote:

On 10/31/11 2:17 PM, Andrea Gavana wrote:

On a completely unrelated note, I am still getting assertion errors from

the AUI (wx.lib.agw one) demo, as per attached screenshot. How do I

debug these? How can I find where the offending line is? It’s curious as

other apps I have work OK with the latest AGW from SVN, but the demo

asserts when I close the main frame…

Running this in the WIT with the demo’s AuiFrame selected:

for c in [obj] + list(obj.Children):

… if c is not c.GetEventHandler():

… print c.class.name, ’ has handler ', c.GetEventHandler().class.name

gives me this:

AuiFrame has handler AuiManager

AuiNotebook has handler AuiManager

Grid has handler EvtHandler

HtmlWindow has handler EvtHandler

AuiNotebook has handler AuiManager

AuiFloatingFrame has handler AuiManager

We can ignore the Grid and HtmlWindow items since they can be expected to clean up after themselves. Are any of the remaining windows calling AuiManager.UnInit so the manager will remove itself from the managed frame’s EventHandler stack? Perhaps we should find a way to do that automatically…

Thanks. I think I have fixed it in the latest SVN revision.

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”

http://xoomer.alice.it/infinity77/