Hot-Keys in wxHtmlWindow

Yes. it turned out to be pretty easy and very functional
with no real problems at all:

Here's what I did:

1. I have already derived my own subclass from wxHtmlCtrl to add
automatic scrolling to keep the active control in view. I added
a few things to this class:

In the constructor:

        self.initAcceleratorKeys = [
                    ( wxACCEL_NORMAL, WXK_PRIOR, ID_PAGE_UP ),
                    ( wxACCEL_NORMAL, WXK_NEXT, ID_PAGE_DOWN ),
                    ( wxACCEL_NORMAL, WXK_UP, ID_SCROLL_UP ),
                    ( wxACCEL_NORMAL, WXK_DOWN, ID_SCROLL_DOWN ),
                    ( wxACCEL_CTRL, WXK_PRIOR, ID_SCROLL_TOP ),
                    ( wxACCEL_CTRL, WXK_NEXT, ID_SCROLL_BOTTOM )
                ]

        EVT_MENU(self, ID_PAGE_UP, self.OnPageUp )
        EVT_MENU(self, ID_PAGE_DOWN, self.OnPageDown )
        EVT_MENU(self, ID_SCROLL_UP, self.OnScrollUp )
        EVT_MENU(self, ID_SCROLL_DOWN, self.OnScrollDown )
        EVT_MENU(self, ID_SCROLL_TOP, self.OnScrolltop )
        EVT_MENU(self, ID_SCROLL_BOTTOM, self.OnScrollBottom )

        self.acceleratorKeys = []
        self.acceleratorKeys.extend(self.initAcceleratorKeys)
        self.SetAcceleratorTable(
                wxAcceleratorTable(self.acceleratorKeys))

2. and a few new methods:

    def OnPageUp(self, evt):
        for i in range(15):
            self.ScrollLines(-1)

    def OnPageDown(self, evt):
        for i in range(15):
            self.ScrollLines(1)

    def OnScrollUp(self, evt):
        self.ScrollLines(-1)

    def OnScrollDown(self, evt):
        self.ScrollLines(+1)

    def OnScrolltop(self, evt):
        while 1:
            vs_y = self.GetViewStart()[1]
            self.ScrollLines(-1)
            if self.GetViewStart()[1] == vs_y:
                break

    def OnScrollBottom(self, evt):
        while 1:
            vs_y = self.GetViewStart()[1]
            self.ScrollLines(+1)
            if self.GetViewStart()[1] == vs_y:
                break

    def AddAcceleratorHandler(self, keyFlags, evtId, keyCode, handler):
        EVT_MENU(self, evtId, handler)
        self.acceleratorKeys.append( (keyFlags, keyCode, evtId) )

    def SetPage(self, pageContents, accelerators = []):
        self.acceleratorKeys = []
        self.acceleratorKeys.extend(self.initAcceleratorKeys)
        self.acceleratorKeys.extend(accelerators)
        wxHtmlWindow.SetPage(self, pageContents)
        self.SetAcceleratorTable(
                wxAcceleratorTable(self.acceleratorKeys))

BTW, I know that there is a ScrollPages method, but I like to scroll
less than a full page so that the user gets some visual effect of up
or down motion.

I also noticed that the keycodes use "prior" and "next" instead of
"page up" and "page down". Is that how keyboards in UK are labeled?
If not, howcome?

3. Then in the constructor for panels added directly or indirectly to
my html window, hook the top window events, eg:

        topWindow.AddAcceleratorHandler(
                wxACCEL_ALT, ID_CLOSE, ord('C'), self.OnCloseButton)
        topWindow.AddAcceleratorHandler(
                wxACCEL_ALT, ID_HELP, ord('H'), self.OnHelpButton)
        topWindow.AddAcceleratorHandler(
                wxACCEL_ALT, ID_EXIT, ord('X'), self.OnExitButton)

So, the event handlers can be down in the client panels.

There are a few shortcomings with this approach:

1.The child panels can only be added into a window
hierarchy that supports this API.

2. The child panels have to know who is passing them their events.

3. No easy way to remove handlers or rebuild all the handlers, for
   example for a page change of a notebook control that includes some,
   but not all, of the hotkeys. But one could work around that by
   writing little dispatchers in the event handlers that branched
   according to which page is visible.

So, I'd rather do what I previously described, but this is perfectly
good solution for me for now.

I was worried that EVT_MENU might not be a simple function call and
that something might break therefore when I tried to set up the
events in the parent from the child panels, but it seems to work
great in my smoke tests so far.

Thanks for the tip.

Al