Propagating an event: I'm just clumsy

Hello, I ran into a problem using the UltimateListCtrl, where the
controls that I place into the control eat clicks. That's
understandable, because that's the way wxWidgets works. The controls
that I'm using happen to be passive in nature (like a wx.Panel, or a
wx.Gauge.

The problem is that if a user clicks on the (passive) control, the
list control doesn't highlight the item. You have to click on a list
item that consists of a string. So I set about trying to propagate
the click up to the Ultimatelistctrl, so that it could 'do its thing'
and highlight the selected row.

I found out pretty quickly that I just don't understand the event
propagation that well, even after reading over the docs on it. It
seemed to me that a simple "event.ResultPropagation(1)" associated
with the inserted panel would work, but it didn't. I kludged together
another solution that does work (calling ProcessEvent() directly), but
it seems inelegant, as as luck would have it, this solution works on
my little example below but does not work in my application (AUI is
involved, and things are more complicated there).

Anyway, sorry for the longness of the post above, but here's the
question...is there a nice simple way to propagate mouse events
straight to the UltimateListCtrl without having to go through the
clumsy position translation and event hackery steps? A runnable code
example is below. The hackery is in "OnMouse".

import wx
from wx.lib.agw import ultimatelistctrl as ULC
import sys

def OnMouse(evt):
        # TRY 1: just let the event bubble up.
        # doesn't work; the event gets to the parent, but the first
row is always selected.
        #evt.ResumePropagation(1)
        #evt.Skip()
        #return

        # TRY 2: explicitly try to route the event up to the parent.
        # WORKS. But it doesn't work in my code if the list is
scrolled. why.
        win = evt.GetEventObject()
        pos = win.ClientToScreen(evt.GetPosition())
        pos = win.GetParent().ScreenToClient(pos)
        evt.m_x = pos[0]
        evt.m_y = pos[1]
        win.GetParent().GetEventHandler().ProcessEvent(evt)

app = wx.PySimpleApp()
frame = wx.Frame(None,title="Uncomment the Bind to let the mouse
events propagate")
listctrl = ULC.UltimateListCtrl(frame,agwStyle=ULC.ULC_REPORT|
ULC.ULC_HAS_VARIABLE_ROW_HEIGHT)

# add the headers
for i in xrange(2): listctrl.InsertColumn(i,"column%d"%i,width=200)

# add some items
for i in xrange(10):
    index = listctrl.InsertStringItem(sys.maxint,"Item%d, Click on the
panel -->"%i)
    progress = wx.Panel(listctrl,size=(-1,25))
    listctrl.SetItemWindow(index,1,progress,expand=True)

    # Uncomment this to let the clicks propagate up to the parent.
    #progress.Bind(wx.EVT_MOUSE_EVENTS,OnMouse)

frame.Show(True)
app.MainLoop()

Sorry, I was using the old google groups interface. Here is the code attached.

ULCproblemshort.py (1.84 KB)

Yes, that is pretty much how it would need to be done. I might have created a new instance of the event for it instead of reusing the current one, but that probably doesn't matter much. The scrolled problem is probably simply that you need to adjust your position for the scrolled offset of the window so it gets the correct coordinates.

Another possible approach that may work is instead of sending fake mouse events you can use the tree's HitTest method to find the item where your mouse cursor is positioned and then just select that item programatically.

···

On 9/22/11 2:43 PM, dhyams wrote:

Sorry, I was using the old google groups interface. Here is the code
attached.

        # TRY 2: explicitly try to route the event up to the parent.
        # WORKS. But it doesn't work in my code if the list is scrolled. why.
        win = evt.GetEventObject()
        pos = win.ClientToScreen(evt.GetPosition())
        pos = win.GetParent().ScreenToClient(pos)
        evt.m_x = pos[0]
        evt.m_y = pos[1]
        win.GetParent().GetEventHandler().ProcessEvent(evt)

--
Robin Dunn
Software Craftsman

Thanks Robin! I'll try playing with the HitTest() method.

What is weird about my sample is that reflecting the mouse events via
"TRY 2" does work perfectly on the sample code, even if the list is
scrolled. However, it does not work in my app when the list is
scrolled, where the ULC is embedded in an AUI pane. I've not yet put
together a sample code for that, but I couldn't think of any reason
offhand why the two situations would be different. I actually created
the example code expecting it not to work when scrolled, but to my
surprise, it did.

···

On Sep 23, 10:18 pm, Robin Dunn <ro...@alldunn.com> wrote:

On 9/22/11 2:43 PM, dhyams wrote:

> Sorry, I was using the old google groups interface. Here is the code
> attached.

> # TRY 2: explicitly try to route the event up to the parent.
> # WORKS. But it doesn't work in my code if the list is scrolled. why.
> win = evt.GetEventObject()
> pos = win.ClientToScreen(evt.GetPosition())
> pos = win.GetParent().ScreenToClient(pos)
> evt.m_x = pos[0]
> evt.m_y = pos[1]
> win.GetParent().GetEventHandler().ProcessEvent(evt)

Yes, that is pretty much how it would need to be done. I might have
created a new instance of the event for it instead of reusing the
current one, but that probably doesn't matter much. The scrolled
problem is probably simply that you need to adjust your position for the
scrolled offset of the window so it gets the correct coordinates.

Another possible approach that may work is instead of sending fake mouse
events you can use the tree's HitTest method to find the item where your
mouse cursor is positioned and then just select that item programatically.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org