Text control and TAB

Annius Groenink wrote:
> A read-only, multiline, rich text control (and possibly other
> combinations) seems to stop TAB traversal. Moreover, it is
> impossible to catch the TAB key explicitly.

Platform, version and sample app?
--
Robin Dunn

I am working with wxpython 2.5.3, python 2.3, Windows XP.

I have managed to reduce the problem: it only happens when I have two
Notebooks in one top level window. My application has a notebook for its
main content, and a notebook containing two logs (normal and detailed).

So for the time being, I guess I need to get rid of the "two logs",
but of course I would prefer to get the issue resolved instead...

Please find a sample app below. When you repeatedly press TAB, the cursor
gets caught in the text control in the lower notebook, never to come out
again.

(In my more complex application, I can magically get the TAB key to circle
the buttons in the first tab of the upper notebook, but not of the second,
which has a splitter embedded in the notebook.)

What I would like to do, is to have the TAB key navigate the controls in
the upper notebook only. If I have to switch to manual management of TAB
navigation, fine, but attempts to do so have so far been successful; I
just can't catch the events I need to manage TAB myself across everything
on the screen.

Annius.

import wx

class App(wx.App):
   def OnInit(
      self
   ) :
      main_window = Frame()
      self.SetTopWindow(main_window)
      return True

class Frame(wx.Frame):
   def __init__(
      self
   ) :
      wx.Frame.__init__(
         self, None, -1,
         "wxPython test",
         wx.DefaultPosition,
         wx.Size(640, 480),
         style = wx.DEFAULT_FRAME_STYLE
               > wx.NO_FULL_REPAINT_ON_RESIZE)
      self.Centre(wx.HORIZONTAL | wx.VERTICAL)

      menu = wx.Menu()
      menu.Append(wx.ID_ANY, "Quit")

      bar = wx.MenuBar()
      bar.Append(menu, "&File")

      self.SetMenuBar(bar)

      splitter = wx.SplitterWindow(
                           self, wx.ID_ANY,
                           style = wx.CLIP_CHILDREN
                                 > wx.SP_LIVE_UPDATE
                                 > wx.SP_3D)
      splitter.SetMinimumPaneSize(100)

      tabs = wx.Notebook(
                           splitter, wx.ID_ANY, style = wx.TAB_TRAVERSAL)

      log = wx.Notebook(
                        splitter, wx.ID_ANY, style = wx.TAB_TRAVERSAL)
      log1 = wx.TextCtrl(
                        log, wx.ID_ANY, style = wx.TE_MULTILINE
                                              > wx.TE_READONLY
                                              > wx.HSCROLL
                                              > wx.TE_PROCESS_TAB
                                              > wx.TAB_TRAVERSAL
                                              > wx.TE_RICH)
      log2 = wx.TextCtrl(
                        log, wx.ID_ANY, style = wx.TE_MULTILINE
                                              > wx.TE_READONLY
                                              > wx.HSCROLL
                                              > wx.TE_PROCESS_TAB
                                              > wx.TAB_TRAVERSAL
                                              > wx.TE_RICH)
      log1.AppendText("[Sun 12:24] Message in log 1")
      log2.AppendText("[Sun 12:24] Message in log 2")
      log.AddPage(log1, "Log 1")
      log.AddPage(log2, "Log 2")

      panel1 = wx.Panel(tabs, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button1 = wx.Button(panel1, wx.ID_ANY, "Button 1")
      button2 = wx.Button(panel1, wx.ID_ANY, "Button 2")
      button1.SetPosition((10, 10))
      button2.SetPosition((10, 50))

      panel2 = wx.SplitterWindow(
                           tabs, wx.ID_ANY,
                           style = wx.CLIP_CHILDREN
                                 > wx.SP_LIVE_UPDATE
                                 > wx.SP_3D)
      panel2.SetMinimumPaneSize(100)
      panel3 = wx.Panel(panel2, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button3 = wx.Button(panel3, wx.ID_ANY, "Button 3")
      button3.SetPosition((10, 10))
      panel4 = wx.Panel(panel2, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button4 = wx.Button(panel4, wx.ID_ANY, "Button 4")
      button4.SetPosition((10, 10))
      panel2.SplitHorizontally(panel3, panel4, 100)

      splitter.SplitHorizontally(tabs, log, 200)

      tabs.AddPage(panel1, "Tab circles")
      tabs.AddPage(panel2, "Tab lose control")

      self.Show(True)

app = App(0)
app.MainLoop()

[in this version of the sample app I sent earlier, you can choose whether
to 'split' the log window or not, and see that the problem only occurs when
there are two notebooks]

split_log = True # set to False to test without double Notebook

import wx

class App(wx.App):
   def OnInit(
      self
   ) :
      main_window = Frame()
      self.SetTopWindow(main_window)
      return True

class Frame(wx.Frame):
   def __init__(
      self
   ) :
      wx.Frame.__init__(
         self, None, -1,
         "wxPython test",
         wx.DefaultPosition,
         wx.Size(640, 480),
         style = wx.DEFAULT_FRAME_STYLE
               > wx.NO_FULL_REPAINT_ON_RESIZE)
      self.Centre(wx.HORIZONTAL | wx.VERTICAL)

      menu = wx.Menu()
      menu.Append(wx.ID_ANY, "Quit")

      bar = wx.MenuBar()
      bar.Append(menu, "&File")

      self.SetMenuBar(bar)

      splitter = wx.SplitterWindow(
                           self, wx.ID_ANY,
                           style = wx.CLIP_CHILDREN
                                 > wx.SP_LIVE_UPDATE
                                 > wx.SP_3D)
      splitter.SetMinimumPaneSize(100)

      tabs = wx.Notebook(
                           splitter, wx.ID_ANY, style = wx.TAB_TRAVERSAL)

      if split_log:
         log = wx.Notebook(
                           splitter, wx.ID_ANY, style = wx.TAB_TRAVERSAL)
         log1 = wx.TextCtrl(
                           log, wx.ID_ANY, style = wx.TE_MULTILINE
                                                 > wx.TE_READONLY
                                                 > wx.HSCROLL
                                                 > wx.TE_PROCESS_TAB
                                                 > wx.TAB_TRAVERSAL
                                                 > wx.TE_RICH)
         log2 = wx.TextCtrl(
                           log, wx.ID_ANY, style = wx.TE_MULTILINE
                                                 > wx.TE_READONLY
                                                 > wx.HSCROLL
                                                 > wx.TE_PROCESS_TAB
                                                 > wx.TAB_TRAVERSAL
                                                 > wx.TE_RICH)
         log1.AppendText("[Sun 12:24] Message in log 1")
         log2.AppendText("[Sun 12:24] Message in log 2")
         log.AddPage(log1, "Log 1")
         log.AddPage(log2, "Log 2")
      else:
         log = wx.TextCtrl(
                              splitter, wx.ID_ANY, style = wx.TE_MULTILINE
                                                         > wx.TE_READONLY
                                                         > wx.HSCROLL
                                                         >
wx.TE_PROCESS_TAB
                                                         >
wx.TAB_TRAVERSAL
                                                         > wx.TE_RICH)
         log.AppendText("[Sun 12:24] Log message")

      panel1 = wx.Panel(tabs, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button1 = wx.Button(panel1, wx.ID_ANY, "Button 1")
      button2 = wx.Button(panel1, wx.ID_ANY, "Button 2")
      button1.SetPosition((10, 10))
      button2.SetPosition((10, 50))

      panel2 = wx.SplitterWindow(
                           tabs, wx.ID_ANY,
                           style = wx.CLIP_CHILDREN
                                 > wx.SP_LIVE_UPDATE
                                 > wx.SP_3D)
      panel2.SetMinimumPaneSize(100)
      panel3 = wx.Panel(panel2, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button3 = wx.Button(panel3, wx.ID_ANY, "Button 3")
      button3.SetPosition((10, 10))
      panel4 = wx.Panel(panel2, wx.ID_ANY, style =
wx.TAB_TRAVERSAL)
      button4 = wx.Button(panel4, wx.ID_ANY, "Button 4")
      button4.SetPosition((10, 10))
      panel2.SplitHorizontally(panel3, panel4, 100)

      splitter.SplitHorizontally(tabs, log, 200)

      tabs.AddPage(panel1, "Tab circles")
      tabs.AddPage(panel2, "Tab lose control")

      self.Show(True)

app = App(0)
app.MainLoop()