[PEAK] Trellis + wx

Sergey Schetinin maluke at gmail.com
Tue Jul 1 19:15:59 EDT 2008


I was prototyping a library to use Trellis for various wx operations
and came across an issue I don't know how to resolve.

I tried to stick to Phillip's advice, so event handlers are
implemented in such a way that they set some attribute (which has
resetting_to=False) of a window component to an instance of some event
class. So a rule to handle events can look like this:

    @maintain
    def on_close_click(self):
        if self.button_close.clicked:
            on_commit(self.close)

It uses @maintain with on_commit instead of @perform because
self.close calls wx.Frame.Close and that will in effect send a new
event which will set more attributes and that is prohibited in
@perform rules. Anyway, this isn't the issue. When the actual
wx.Frame.Close is called that triggers another handler which sets
.closing to an instance of CancellableEvent. That has a cancel method
which simply sets .cancelled = True for that event. So, the event
handler for EVT_CLOSE should decide before returning if the event
should be propagated (and window closed) or if it should be stopped
(evt.Skip() or evt.Veto()).  Now let's see how a rule that decides
that could like like:

    @maintain
    def on_close(self):
    if self.closing:
        if not self.button_close.clicked:
            self.closing.cancel()

This makes sure the window only closes in response to button_close. So
it should just work, right? In fact it doesn't, because the on_close
rule runs too late.

This call chain would work:

got click event from wx
    -> atomically
        -> process click event (button_close.clicked = True)
            -> on_close_click
                -> on_commit(self.close)
        -> frame.Close
            -> process close event (.closing = CancellableEvent)
                -> on_close
                    -> closing.cancel()

But the actual chain is different, the on_close is only called later,
before the end of the pulse, at the "atomically" level which makes it
too late to influence the propagation of CloseEvent. One way to work
around this would be avoid nested event handler calls, so the .close
would have not to immediately call wx.Frame.Close but use wx.CallAfter
or otherwise schedule the call. But would break the on_close rule,
because it wouldn't know the source of the event (button_close.clicked
would revert back to False).

Can anything be done for such cases? Is it even possible to make sure
all dependent rules recalculate before EVT_CLOSE handler exits without
violating some basic assumptions?

If my explanation is incomprehensible, please let me know, I'll try to
explain it some other way.

-- 
Best Regards,
Sergey Schetinin

http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter



More information about the PEAK mailing list