Found it!
Inside of TextCtrlAutoComplete.py, there is this basic handler which happens
to be bound to both wx.EVT_SIZE and wx.EVT_MOVE **not only of itself, but of
all of its parents, grandparents...etc... all the way up the hierarchy**.
<code snipped>
Well... somewhere in the middle of my working on relatively unrelated stuff
last night, the event.Skip() line got commented out of that routing. I
don't know if it was just a mouse button slip as I was passing by, or what.
But that only little event.Skip() got commented out, and as a result the
TextCtrlAutoComplete holds up an entire branch of my main window.
Everything from there on up is prevented from resizing because wx.EVT_SIZE
is caught by one little control's event handler and not skipped.
So I'm curious what can be learned from this. One must, of course, be
responsible for one's every move when programming, including accidentally
commenting out even a single line. That is simply part of the trade. But,
with that acknowledged, intuitively I feel that the TextCtrlAutoComplete
should be built a little differently in order to not throw such great
consequences to its whole parent system if the control itself is for some
reason altered. I'm not trying to make a big point here, just taking it as
a learning opportunity.
It strikes me as odd that a control should need to bind its On(self)Changed
method to EVT_MOVE and EVT_SIZE at the level of *each* of its containers /
ancestors. I remember when I first read through the control in order to
start making use of it in my app, that recursive binding section bothered me
a little bit but I decided to get back to that later.
When you move a top level window, the children don't receive move
events, because a windows position is relative to its parent and that
hasn't changed. The PopupWindow is positioned absolutely, though, so
it needs to be updated and a recursive event handler is how the author
chose to implement it. The size event doesn't need to be in there.
This isn't how I'd implement it, though. I'd use an idle event handler
to sync the position and state.
Try replacing the recursive event handler with this:
self.Bind(wx.EVT_IDLE, self.EnsurePositionAndSize)
def EnsurePositionAndSize(self, evt):
""" Make sure that the controls size and position
match the parent controls current size and position"""
#hax - the sizing code should be in a seperate method
# called both here and from _showDropDown
if self.dropdown.IsShown():
self._showDropDown(True)
This has a behavior change, which I prefer. In the original code, when
the window was moved or resized with the dropdown shown, the dropdown
was hidden. This code keeps the dropdown shown, and just updates the
size and position. You can get the old behavior with some extra logic
to compare the size and position - this is left as an exercise for the
reader.
(If the original author [or anyone else] wants to add this to the
version on the wiki, feel free)
As for the problem with removing evt.Skip() causing problems, this is
a general problem you need to be aware of. It can even be platform
specific, where a missing evt.Skip() will have no visible effect on,
say, Windows but will prevent updates under Gtk. In general, you
should *always* Skip() unless you know exactly why you aren't, and
what behavior you are preventing by doing so. I'd like it if the
default changed so you had to explicitly block events instead of
explicitly skipping, but since it's a major change and would break
almost all currently working code, I don't really see much chance of
it happening.
···
On 6/2/07, Eric Ongerth <ericongerth@gmail.com> wrote: