]> git.saurik.com Git - wxWidgets.git/commitdiff
Added wx.lib.foldpanelbar, Andrea Gavana's port of Jorgen Bodde's C++
authorRobin Dunn <robin@alldunn.com>
Wed, 30 Mar 2005 22:58:23 +0000 (22:58 +0000)
committerRobin Dunn <robin@alldunn.com>
Wed, 30 Mar 2005 22:58:23 +0000 (22:58 +0000)
wxFoldPanelBar classes to Python.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33207 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

wxPython/demo/FoldPanelBar.py [new file with mode: 0644]
wxPython/demo/Main.py
wxPython/docs/CHANGES.txt
wxPython/wx/lib/foldpanelbar.py [new file with mode: 0644]

diff --git a/wxPython/demo/FoldPanelBar.py b/wxPython/demo/FoldPanelBar.py
new file mode 100644 (file)
index 0000000..9664b06
--- /dev/null
@@ -0,0 +1,906 @@
+
+import  wx
+import wx.lib.foldpanelbar as fpb
+
+
+# ----------------------------------------------------------------------------
+# Extended Demo Implementation
+#
+# This demo shows how to use custom CaptionBar styles and custom icons for
+# the caption bars. here i used the standard Windows XP icons for the
+# collapsed and expanded state.
+# ----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------
+# different icons for the collapsed/expanded states.
+# Taken from standard Windows XP collapsed/expanded states.
+#----------------------------------------------------------------------
+
+def GetCollapsedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x8eIDAT8\x8d\xa5\x93-n\xe4@\x10\x85?g\x03\n6lh)\xc4\xd2\x12\xc3\x81\
+\xd6\xa2I\x90\x154\xb9\x81\x8f1G\xc8\x11\x16\x86\xcd\xa0\x99F\xb3A\x91\xa1\
+\xc9J&\x96L"5lX\xcc\x0bl\xf7v\xb2\x7fZ\xa5\x98\xebU\xbdz\xf5\\\x9deW\x9f\xf8\
+H\\\xbfO|{y\x9dT\x15P\x04\x01\x01UPUD\x84\xdb/7YZ\x9f\xa5\n\xce\x97aRU\x8a\
+\xdc`\xacA\x00\x04P\xf0!0\xf6\x81\xa0\xf0p\xff9\xfb\x85\xe0|\x19&T)K\x8b\x18\
+\xf9\xa3\xe4\xbe\xf3\x8c^#\xc9\xd5\n\xa8*\xc5?\x9a\x01\x8a\xd2b\r\x1cN\xc3\
+\x14\t\xce\x97a\xb2F0Ks\xd58\xaa\xc6\xc5\xa6\xf7\xdfya\xe7\xbdR\x13M2\xf9\
+\xf9qKQ\x1fi\xf6-\x00~T\xfac\x1dq#\x82,\xe5q\x05\x91D\xba@\xefj\xba1\xf0\xdc\
+zzW\xcff&\xb8,\x89\xa8@Q\xd6\xaaf\xdfRm,\xee\xb1BDxr#\xae\xf5|\xddo\xd6\xe2H\
+\x18\x15\x84\xa0q@]\xe54\x8d\xa3\xedf\x05M\xe3\xd8Uy\xc4\x15\x8d\xf5\xd7\x8b\
+~\x82\x0fh\x0e"\xb0\xad,\xee\xb8c\xbb\x18\xe7\x8e;6\xa5\x89\x04\xde\xff\x1c\
+\x16\xef\xe0p\xfa>\x19\x11\xca\x8d\x8d\xe0\x93\x1b\x01\xd8m\xf3(;x\xa5\xef=\
+\xb7w\xf3\x1d$\x7f\xc1\xe0\xbd\xa7\xeb\xa0(,"Kc\x12\xc1+\xfd\xe8\tI\xee\xed)\
+\xbf\xbcN\xc1{D\x04k\x05#\x12\xfd\xf2a\xde[\x81\x87\xbb\xdf\x9cr\x1a\x87\xd3\
+0)\xba>\x83\xd5\xb97o\xe0\xaf\x04\xff\x13?\x00\xd2\xfb\xa9`z\xac\x80w\x00\
+\x00\x00\x00IEND\xaeB`\x82' 
+
+def GetCollapsedIconBitmap():
+    return wx.BitmapFromImage(GetCollapsedIconImage())
+
+def GetCollapsedIconImage():
+    import cStringIO
+    stream = cStringIO.StringIO(GetCollapsedIconData())
+    return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def GetExpandedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x01\x9fIDAT8\x8d\x95\x93\xa1\x8e\xdc0\x14EO\xb2\xc4\xd0\xd2\x12\xb7(mI\
+\xa4%V\xd1lQT4[4-\x9a\xfe\xc1\xc2|\xc6\xc2~BY\x83:A3E\xd3\xa0*\xa4\xd2\x90H!\
+\x95\x0c\r\r\x1fK\x81g\xb2\x99\x84\xb4\x0fY\xd6\xbb\xc7\xf7>=\'Iz\xc3\xbcv\
+\xfbn\xb8\x9c\x15 \xe7\xf3\xc7\x0fw\xc9\xbc7\x99\x03\x0e\xfbn0\x99F+\x85R\
+\x80RH\x10\x82\x08\xde\x05\x1ef\x90+\xc0\xe1\xd8\ryn\xd0Z-\\A\xb4\xd2\xf7\
+\x9e\xfbwoF\xc8\x088\x1c\xbbae\xb3\xe8y&\x9a\xdf\xf5\xbd\xe7\xfem\x84\xa4\
+\x97\xccYf\x16\x8d\xdb\xb2a]\xfeX\x18\xc9s\xc3\xe1\x18\xe7\x94\x12cb\xcc\xb5\
+\xfa\xb1l8\xf5\x01\xe7\x84\xc7\xb2Y@\xb2\xcc0\x02\xb4\x9a\x88%\xbe\xdc\xb4\
+\x9e\xb6Zs\xaa74\xadg[6\x88<\xb7]\xc6\x14\x1dL\x86\xe6\x83\xa0\x81\xba\xda\
+\x10\x02x/\xd4\xd5\x06\r\x840!\x9c\x1fM\x92\xf4\x86\x9f\xbf\xfe\x0c\xd6\x9ae\
+\xd6u\x8d \xf4\xf5\x165\x9b\x8f\x04\xe1\xc5\xcb\xdb$\x05\x90\xa97@\x04lQas\
+\xcd*7\x14\xdb\x9aY\xcb\xb8\\\xe9E\x10|\xbc\xf2^\xb0E\x85\xc95_\x9f\n\xaa/\
+\x05\x10\x81\xce\xc9\xa8\xf6><G\xd8\xed\xbbA)X\xd9\x0c\x01\x9a\xc6Q\x14\xd9h\
+[\x04\xda\xd6c\xadFkE\xf0\xc2\xab\xd7\xb7\xc9\x08\x00\xf8\xf6\xbd\x1b\x8cQ\
+\xd8|\xb9\x0f\xd3\x9a\x8a\xc7\x08\x00\x9f?\xdd%\xde\x07\xda\x93\xc3{\x19C\
+\x8a\x9c\x03\x0b8\x17\xe8\x9d\xbf\x02.>\x13\xc0n\xff{PJ\xc5\xfdP\x11""<\xbc\
+\xff\x87\xdf\xf8\xbf\xf5\x17FF\xaf\x8f\x8b\xd3\xe6K\x00\x00\x00\x00IEND\xaeB\
+`\x82' 
+
+def GetExpandedIconBitmap():
+    return wx.BitmapFromImage(GetExpandedIconImage())
+
+def GetExpandedIconImage():
+    import cStringIO
+    stream = cStringIO.StringIO(GetExpandedIconData())
+    return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def GetMondrianData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
+\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
+ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
+o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
+\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
+\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
+\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82' 
+
+def GetMondrianBitmap():
+    return wx.BitmapFromImage(GetMondrianImage())
+
+def GetMondrianImage():
+    import cStringIO
+    stream = cStringIO.StringIO(GetMondrianData())
+    return wx.ImageFromStream(stream)
+
+def GetMondrianIcon():
+    icon = wx.EmptyIcon()
+    icon.CopyFromBitmap(GetMondrianBitmap())
+    return icon
+
+# ----------------------------------------------------------------------------
+# Beginning Of Extended Demo
+# ----------------------------------------------------------------------------
+
+class Extended(wx.Frame):
+    
+    def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+                 size=(700,650), style=wx.DEFAULT_FRAME_STYLE):
+
+        wx.Frame.__init__(self, parent, id, title, pos, size, style)
+
+        self._flags = 0
+        
+        self.SetIcon(GetMondrianIcon())
+        self.SetMenuBar(self.CreateMenuBar())
+
+        self.statusbar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
+        self.statusbar.SetStatusWidths([-4, -3])
+        self.statusbar.SetStatusText("Andrea Gavana @ 23 Mar 2005", 0)
+        self.statusbar.SetStatusText("Welcome to wxPython!", 1)
+
+        self._leftWindow1 = wx.SashLayoutWindow(self, 101, wx.DefaultPosition,
+                                                wx.Size(200, 1000), wx.NO_BORDER |
+                                                wx.SW_3D | wx.CLIP_CHILDREN)
+
+        self._leftWindow1.SetDefaultSize(wx.Size(220, 1000))
+        self._leftWindow1.SetOrientation(wx.LAYOUT_VERTICAL)
+        self._leftWindow1.SetAlignment(wx.LAYOUT_LEFT)
+        self._leftWindow1.SetSashVisible(wx.SASH_RIGHT, True)
+        self._leftWindow1.SetExtraBorderSize(10)
+
+        self._pnl = 0
+
+        # will occupy the space not used by the Layout Algorithm
+        self.remainingSpace = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
+        wx.StaticText(self.remainingSpace, -1,
+                      "Use your imagination for what kinds of things to put in this window...",
+                      (15,30))
+
+        self.ID_WINDOW_TOP = 100
+        self.ID_WINDOW_LEFT1 = 101
+        self.ID_WINDOW_RIGHT1 = 102
+        self.ID_WINDOW_BOTTOM = 103
+    
+        self._leftWindow1.Bind(wx.EVT_SASH_DRAGGED_RANGE, self.OnFoldPanelBarDrag,
+                               id=100, id2=103)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_SCROLL, self.OnSlideColour)
+        
+        self.ReCreateFoldPanel(0)
+        
+
+    def OnSize(self, event):
+
+        wx.LayoutAlgorithm().LayoutWindow(self, self.remainingSpace)
+        event.Skip()
+        
+
+    def OnQuit(self, event):
+        self.Destroy()
+
+
+    def OnAbout(self, event):
+
+        msg = "This is the about dialog of the FoldPanelBar demo.\n\n" + \
+              "Author: Andrea Gavana @ 23 Mar 2005\n\n" + \
+              "Please report any bug/requests or improvements\n" + \
+              "To me at the following adresses:\n\n" + \
+              "andrea.gavana@agip.it\n" + "andrea_gavana@tin.it\n\n" + \
+              "Based On Julian Smart C++ demo implementation.\n\n" + \
+              "Welcome To wxPython " + wx.VERSION_STRING + "!!"
+              
+        dlg = wx.MessageDialog(self, msg, "FoldPanelBar Extended Demo",
+                               wx.OK | wx.ICON_INFORMATION)
+        dlg.SetFont(wx.Font(8, wx.NORMAL, wx.NORMAL, wx.NORMAL, False, "Verdana"))
+        dlg.ShowModal()
+        dlg.Destroy()
+
+
+    def OnToggleWindow(self, event):
+        
+        self._leftWindow1.Show(not self._leftWindow1.IsShown())
+        # Leaves bits of itself behind sometimes
+        wx.LayoutAlgorithm().LayoutWindow(self, self.remainingSpace)
+        self.remainingSpace.Refresh()
+
+        event.Skip()
+        
+
+    def OnFoldPanelBarDrag(self, event):
+
+        if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
+            return
+
+        if event.GetId() == self.ID_WINDOW_LEFT1:
+            self._leftWindow1.SetDefaultSize(wx.Size(event.GetDragRect().width, 1000))
+
+
+        # Leaves bits of itself behind sometimes
+        wx.LayoutAlgorithm().LayoutWindow(self, self.remainingSpace)
+        self.remainingSpace.Refresh()
+
+        event.Skip()
+        
+
+    def ReCreateFoldPanel(self, fpb_flags):
+
+        # delete earlier panel
+        self._leftWindow1.DestroyChildren()
+
+        # recreate the foldpanelbar
+
+        self._pnl = fpb.FoldPanelBar(self._leftWindow1, -1, wx.DefaultPosition,
+                                     wx.Size(-1,-1), fpb.FPB_DEFAULT_STYLE, fpb_flags)
+
+        Images = wx.ImageList(16,16)
+        Images.Add(GetExpandedIconBitmap())
+        Images.Add(GetCollapsedIconBitmap())
+            
+        item = self._pnl.AddFoldPanel("Caption Colours", collapsed=False,
+                                      foldIcons=Images)
+
+        self._pnl.AddFoldPanelWindow(item, wx.StaticText(item, -1, "Adjust The First Colour"),
+                                     fpb.FPB_ALIGN_WIDTH, 5, 20) 
+
+        # RED color spin control
+        self._rslider1 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._rslider1, fpb.FPB_ALIGN_WIDTH, 2, 20) 
+
+        # GREEN color spin control
+        self._gslider1 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._gslider1, fpb.FPB_ALIGN_WIDTH, 0, 20) 
+
+        # BLUE color spin control
+        self._bslider1 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._bslider1, fpb.FPB_ALIGN_WIDTH,  0, 20) 
+        
+        self._pnl.AddFoldPanelSeparator(item)
+
+        self._pnl.AddFoldPanelWindow(item, wx.StaticText(item, -1, "Adjust The Second Colour"),
+                                     fpb.FPB_ALIGN_WIDTH, 5, 20) 
+
+        # RED color spin control
+        self._rslider2 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._rslider2, fpb.FPB_ALIGN_WIDTH, 2, 20) 
+
+        # GREEN color spin control
+        self._gslider2 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._gslider2, fpb.FPB_ALIGN_WIDTH, 0, 20) 
+
+        # BLUE color spin control
+        self._bslider2 = wx.Slider(item, -1, 0, 0, 255)
+        self._pnl.AddFoldPanelWindow(item, self._bslider2, fpb.FPB_ALIGN_WIDTH, 0, 20) 
+
+        self._pnl.AddFoldPanelSeparator(item)
+        
+        button1 = wx.Button(item, wx.ID_ANY, "Apply To All")
+        button1.Bind(wx.EVT_BUTTON, self.OnExpandMe)
+        self._pnl.AddFoldPanelWindow(item, button1)
+
+        # read back current gradients and set the sliders
+        # for the colour which is now taken as default
+
+        style = self._pnl.GetCaptionStyle(item)
+        col = style.GetFirstColour()
+
+        self._rslider1.SetValue(col.Red())
+        self._gslider1.SetValue(col.Green())
+        self._bslider1.SetValue(col.Blue())
+
+        col = style.GetSecondColour()
+        self._rslider2.SetValue(col.Red())
+        self._gslider2.SetValue(col.Green())
+        self._bslider2.SetValue(col.Blue())
+
+        # put down some caption styles from which the user can
+        # select to show how the current or all caption bars will look like
+
+        item = self._pnl.AddFoldPanel("Caption Style", False, foldIcons=Images)
+
+        self.ID_USE_VGRADIENT = wx.NewId()
+        self.ID_USE_HGRADIENT = wx.NewId()
+        self.ID_USE_SINGLE = wx.NewId()
+        self.ID_USE_RECTANGLE = wx.NewId()
+        self.ID_USE_FILLED_RECTANGLE = wx.NewId()
+        
+        currStyle =  wx.RadioButton(item, self.ID_USE_VGRADIENT, "&Vertical Gradient")
+        self._pnl.AddFoldPanelWindow(item, currStyle, fpb.FPB_ALIGN_WIDTH,
+                                     fpb.FPB_DEFAULT_SPACING, 10)
+        
+        currStyle.SetValue(True)
+
+        radio1 = wx.RadioButton(item, self.ID_USE_HGRADIENT, "&Horizontal Gradient")
+        radio2 = wx.RadioButton(item, self.ID_USE_SINGLE, "&Single Colour")
+        radio3 = wx.RadioButton(item, self.ID_USE_RECTANGLE, "&Rectangle Box")
+        radio4 = wx.RadioButton(item, self.ID_USE_FILLED_RECTANGLE, "&Filled Rectangle Box")
+
+        currStyle.Bind(wx.EVT_RADIOBUTTON, self.OnStyleChange)
+        radio1.Bind(wx.EVT_RADIOBUTTON, self.OnStyleChange)
+        radio2.Bind(wx.EVT_RADIOBUTTON, self.OnStyleChange)
+        radio3.Bind(wx.EVT_RADIOBUTTON, self.OnStyleChange)
+        radio4.Bind(wx.EVT_RADIOBUTTON, self.OnStyleChange)
+        
+        self._pnl.AddFoldPanelWindow(item, radio1, fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 10) 
+        self._pnl.AddFoldPanelWindow(item, radio2, fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 10) 
+        self._pnl.AddFoldPanelWindow(item, radio3, fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 10) 
+        self._pnl.AddFoldPanelWindow(item, radio4, fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 10) 
+
+        self._pnl.AddFoldPanelSeparator(item)
+
+        self._single = wx.CheckBox(item, -1, "&Only This Caption")
+        self._pnl.AddFoldPanelWindow(item, self._single, fpb.FPB_ALIGN_WIDTH,
+                                     fpb.FPB_DEFAULT_SPACING, 10) 
+
+        # one more panel to finish it
+
+        cs = fpb.CaptionBarStyle()
+        cs.SetCaptionStyle(fpb.CAPTIONBAR_RECTANGLE)
+
+        item = self._pnl.AddFoldPanel("Misc Stuff", collapsed=True, foldIcons=Images,
+                                      cbstyle=cs)
+
+        button2 = wx.Button(item, wx.NewId(), "Collapse All")        
+        self._pnl.AddFoldPanelWindow(item, button2) 
+        self._pnl.AddFoldPanelWindow(item, wx.StaticText(item, -1, "Enter Some Comments"),
+                                     fpb.FPB_ALIGN_WIDTH, 5, 20) 
+        self._pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, -1, "Comments"),
+                                     fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 10)
+
+        button2.Bind(wx.EVT_BUTTON, self.OnCollapseMe)
+        self.radiocontrols = [currStyle, radio1, radio2, radio3, radio4]
+        
+        self._leftWindow1.SizeWindows()
+        
+
+    def OnCreateBottomStyle(self, event):
+
+        # recreate with style collapse to bottom, which means
+        # all panels that are collapsed are placed at the bottom,
+        # or normal
+        
+        if event.IsChecked():
+            self._flags = self._flags | fpb.FPB_COLLAPSE_TO_BOTTOM
+        else:
+            self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM
+
+        self.ReCreateFoldPanel(self._flags)
+
+
+    def OnCreateNormalStyle(self, event):
+
+        # recreate with style where only one panel at the time is
+        # allowed to be opened
+        
+        # TODO: Not yet implemented even in the C++ class!!!!
+
+        if event.IsChecked():
+            self._flags = self._flags | fpb.FPB_SINGLE_FOLD
+        else:
+            self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD
+
+        self.ReCreateFoldPanel(self._flags)
+
+
+    def OnCollapseMe(self, event):
+
+        for i in range(0, self._pnl.GetCount()):
+            item = self._pnl.GetFoldPanel(i)
+            self._pnl.Collapse(item)
+
+
+    def OnExpandMe(self, event):
+
+        col1 = wx.Colour(self._rslider1.GetValue(), self._gslider1.GetValue(),
+                         self._bslider1.GetValue())
+        col2 = wx.Colour(self._rslider2.GetValue(), self._gslider2.GetValue(),
+                         self._bslider2.GetValue())
+
+        style = fpb.CaptionBarStyle()
+
+        style.SetFirstColour(col1)
+        style.SetSecondColour(col2)
+
+        counter = 0
+        for items in self.radiocontrols:
+            if items.GetValue():
+                break
+            counter = counter + 1
+            
+        if counter == 0:
+            mystyle = fpb.CAPTIONBAR_GRADIENT_V
+        elif counter == 1:
+            mystyle = fpb.CAPTIONBAR_GRADIENT_H
+        elif counter == 2:
+            mystyle = fpb.CAPTIONBAR_SINGLE
+        elif counter == 3:
+            mystyle = fpb.CAPTIONBAR_RECTANGLE
+        else:
+            mystyle = fpb.CAPTIONBAR_FILLED_RECTANGLE
+
+        style.SetCaptionStyle(mystyle)
+        self._pnl.ApplyCaptionStyleAll(style)
+
+
+    def OnSlideColour(self, event):
+
+        col1 = wx.Colour(self._rslider1.GetValue(), self._gslider1.GetValue(),
+                         self._bslider1.GetValue())
+        col2 = wx.Colour(self._rslider2.GetValue(), self._gslider2.GetValue(),
+                         self._bslider2.GetValue())
+
+        style = fpb.CaptionBarStyle()
+
+        counter = 0
+        for items in self.radiocontrols:
+            if items.GetValue():
+                break
+            
+            counter = counter + 1
+
+        if counter == 0:
+            mystyle = fpb.CAPTIONBAR_GRADIENT_V
+        elif counter == 1:
+            mystyle = fpb.CAPTIONBAR_GRADIENT_H
+        elif counter == 2:
+            mystyle = fpb.CAPTIONBAR_SINGLE
+        elif counter == 3:
+            mystyle = fpb.CAPTIONBAR_RECTANGLE
+        else:
+            mystyle = fpb.CAPTIONBAR_FILLED_RECTANGLE
+            
+        style.SetFirstColour(col1)
+        style.SetSecondColour(col2)
+        style.SetCaptionStyle(mystyle)
+
+        item = self._pnl.GetFoldPanel(0)
+        self._pnl.ApplyCaptionStyle(item, style)
+        
+
+    def OnStyleChange(self, event):
+
+        style = fpb.CaptionBarStyle()
+        
+        eventid = event.GetId()
+        
+        if eventid == self.ID_USE_HGRADIENT:
+            style.SetCaptionStyle(fpb.CAPTIONBAR_GRADIENT_H)
+            
+        elif eventid == self.ID_USE_VGRADIENT:
+            style.SetCaptionStyle(fpb.CAPTIONBAR_GRADIENT_V)
+            
+        elif eventid == self.ID_USE_SINGLE:
+            style.SetCaptionStyle(fpb.CAPTIONBAR_SINGLE)
+            
+        elif eventid == self.ID_USE_RECTANGLE:
+            style.SetCaptionStyle(fpb.CAPTIONBAR_RECTANGLE)
+            
+        elif eventid == self.ID_USE_FILLED_RECTANGLE:
+            style.SetCaptionStyle(fpb.CAPTIONBAR_FILLED_RECTANGLE)
+                
+        else:
+            raise "ERROR: Undefined Style Selected For CaptionBar: " + repr(eventid)
+
+        col1 = wx.Colour(self._rslider1.GetValue(), self._gslider1.GetValue(),
+                         self._bslider1.GetValue())
+        col2 = wx.Colour(self._rslider2.GetValue(), self._gslider2.GetValue(),
+                         self._bslider2.GetValue())
+
+        style.SetFirstColour(col1)
+        style.SetSecondColour(col2)
+
+        if self._single.GetValue():
+            item = self._pnl.GetFoldPanel(1)
+            self._pnl.ApplyCaptionStyle(item, style)
+        else:
+            self._pnl.ApplyCaptionStyleAll(style)
+    
+
+    def CreateMenuBar(self, with_window=False):
+
+        # Make a menubar
+        file_menu = wx.Menu()
+
+        FPBTEST_QUIT = wx.NewId()
+        FPBTEST_REFRESH = wx.NewId()
+        FPB_BOTTOM_STICK = wx.NewId()
+        FPB_SINGLE_FOLD = wx.NewId()
+        FPBTEST_TOGGLE_WINDOW = wx.NewId()
+        FPBTEST_ABOUT = wx.NewId()
+        
+        file_menu.Append(FPBTEST_QUIT, "&Exit")
+
+        option_menu = None
+
+        if with_window:
+            # Dummy option
+            option_menu = wx.Menu()
+            option_menu.Append(FPBTEST_REFRESH, "&Refresh picture")
+
+        # make fold panel menu
+        
+        fpb_menu = wx.Menu()
+        fpb_menu.AppendCheckItem(FPB_BOTTOM_STICK, "Create with &fpb.FPB_COLLAPSE_TO_BOTTOM")
+        
+        # Not Yet Implemented In The C++ class!!!
+        # fpb_menu.AppendCheckItem(FPB_SINGLE_FOLD, _T("Create with &FPB_SINGLE_FOLD"))
+
+        fpb_menu.AppendSeparator()
+        fpb_menu.Append(FPBTEST_TOGGLE_WINDOW, "&Toggle FoldPanelBar")
+
+        help_menu = wx.Menu()
+        help_menu.Append(FPBTEST_ABOUT, "&About")
+
+        menu_bar = wx.MenuBar()
+
+        menu_bar.Append(file_menu, "&File")
+        menu_bar.Append(fpb_menu, "&FoldPanel")
+        
+        if option_menu:
+            menu_bar.Append(option_menu, "&Options")
+            
+        menu_bar.Append(help_menu, "&Help")
+
+        self.Bind(wx.EVT_MENU, self.OnAbout, id=FPBTEST_ABOUT)
+        self.Bind(wx.EVT_MENU, self.OnQuit, id=FPBTEST_QUIT)
+        self.Bind(wx.EVT_MENU, self.OnToggleWindow, id=FPBTEST_TOGGLE_WINDOW)
+        self.Bind(wx.EVT_MENU, self.OnCreateBottomStyle, id=FPB_BOTTOM_STICK)
+        self.Bind(wx.EVT_MENU, self.OnCreateNormalStyle, id=FPB_SINGLE_FOLD)
+
+        return menu_bar
+
+
+# ----------------------------------------------------------------------------
+# Collapsed Demo Implementation
+# ----------------------------------------------------------------------------
+
+class FoldTestPanel(wx.Panel):
+
+    def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.NO_BORDER | wx.TAB_TRAVERSAL):
+        
+        wx.Panel.__init__(self, parent, id, pos, size, style)
+
+        self.CreateControls()
+        self.GetSizer().Fit(self)
+        self.GetSizer().SetSizeHints(self)
+        self.GetSizer().Layout()
+
+        self.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption)
+
+
+    def OnPressCaption(self, event):
+        event.Skip()
+
+    def CreateControls(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        self.SetSizer(sizer)
+        
+        subpanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
+                            wx.NO_BORDER | wx.TAB_TRAVERSAL)
+        sizer.Add(subpanel, 1, wx.GROW | wx.ADJUST_MINSIZE, 5)
+
+        subsizer = wx.BoxSizer(wx.VERTICAL)
+        subpanel.SetSizer(subsizer)
+        itemstrings = ["One", "Two", "Three"]
+
+        item5 = wx.Choice(subpanel, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
+                          itemstrings, 0)
+        
+        subsizer.Add(item5, 0, wx.GROW | wx.ALL, 5)
+        
+        item6 = wx.TextCtrl(subpanel, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize,
+                            wx.TE_MULTILINE)
+        subsizer.Add(item6, 1, wx.GROW | wx.ALL, 5)
+
+        item7 = wx.RadioButton(subpanel, wx.ID_ANY, "I Like This", wx.DefaultPosition,
+                               wx.DefaultSize, 0)
+        item7.SetValue(True)
+        subsizer.Add(item7, 0, wx.ALIGN_LEFT | wx.ALL, 5)
+
+        item8 = wx.RadioButton(subpanel, wx.ID_ANY, "I Hate It", wx.DefaultPosition,
+                               wx.DefaultSize, 0)
+        item8.SetValue(False)
+        subsizer.Add(item8, 0, wx.ALIGN_LEFT | wx.ALL, 5)
+
+
+# ----------------------------------------------------------------------------
+
+class Collapsed(wx.Frame):
+
+    def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+                 size=(400,300), style=wx.DEFAULT_FRAME_STYLE):
+
+        wx.Frame.__init__(self, parent, id, title, pos, size, style)
+        
+        self.SetIcon(GetMondrianIcon())
+        self.SetMenuBar(self.CreateMenuBar())
+
+        self.statusbar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
+        self.statusbar.SetStatusWidths([-4, -3])
+        self.statusbar.SetStatusText("Andrea Gavana @ 23 Mar 2005", 0)
+        self.statusbar.SetStatusText("Welcome to wxPython!", 1)
+
+        self.CreateFoldBar()
+        
+
+    def CreateFoldBar(self, vertical=True):
+        
+        if vertical:
+            self.SetSize((500,600))
+        else:
+            self.SetSize((700,300))
+
+        newstyle = (vertical and [fpb.FPB_VERTICAL] or [fpb.FPB_HORIZONTAL])[0]
+
+        bar = fpb.FoldPanelBar(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
+                           fpb.FPB_DEFAULT_STYLE | newstyle, fpb.FPB_COLLAPSE_TO_BOTTOM)
+
+        item = bar.AddFoldPanel("Test me", collapsed=False)
+        button1 = wx.Button(item, wx.ID_ANY, "Collapse Me")
+        button1.Bind(wx.EVT_BUTTON, self.OnCollapseMe)
+        
+        bar.AddFoldPanelWindow(item, button1, fpb.FPB_ALIGN_LEFT)
+
+        item = bar.AddFoldPanel("Test me too!", collapsed=True)
+
+        button2 = wx.Button(item, wx.ID_ANY, "Expand First One")
+        button2.Bind(wx.EVT_BUTTON, self.OnExpandMe)
+        
+        bar.AddFoldPanelWindow(item, button2)
+        bar.AddFoldPanelSeparator(item)
+
+        newfoldpanel = FoldTestPanel(item, wx.ID_ANY)
+        bar.AddFoldPanelWindow(item, newfoldpanel)
+
+        bar.AddFoldPanelSeparator(item)
+
+        bar.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),
+                               fpb.FPB_ALIGN_LEFT, fpb.FPB_DEFAULT_SPACING, 20)
+
+        item = bar.AddFoldPanel("Some Opinions ...", collapsed=False)
+        bar.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "I Like This"))
+
+        if vertical:
+            # do not add this for horizontal for better presentation
+            bar.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "And also this"))
+            bar.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "And gimme this too"))
+
+        bar.AddFoldPanelSeparator(item)
+
+        bar.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "Check this too if you like"))
+
+        if vertical:
+            # do not add this for horizontal for better presentation
+            bar.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "What about this"))
+
+        item = bar.AddFoldPanel("Choose one ...", collapsed=False)
+        bar.AddFoldPanelWindow(item, wx.StaticText(item, wx.ID_ANY, "Enter your comment"))
+        bar.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),
+                               fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 20)
+
+        if hasattr(self, "pnl"):
+            self.pnl.Destroy()
+
+        self.pnl = bar
+
+        size = self.GetClientSize()
+        self.pnl.SetDimensions(0, 0, size.GetWidth(), size.GetHeight())
+
+
+    def CreateMenuBar(self):
+
+        FoldPanelBarTest_Quit = wx.NewId()
+        FoldPanelBarTest_About = wx.NewId()
+        FoldPanelBarTest_Horizontal = wx.NewId()
+        FoldPanelBarTest_Vertical = wx.NewId()
+        
+        menuFile = wx.Menu()
+        menuFile.Append(FoldPanelBarTest_Horizontal, "&Horizontal\tAlt-H")
+        menuFile.Append(FoldPanelBarTest_Vertical, "&Vertical\tAlt-V")
+        menuFile.AppendSeparator()
+        menuFile.Append(FoldPanelBarTest_Quit, "E&xit\tAlt-X", "Quit This Program")
+
+        helpMenu = wx.Menu()
+        helpMenu.Append(FoldPanelBarTest_About, "&About...\tF1", "Show About Dialog")
+
+        self.FoldPanelBarTest_Vertical = FoldPanelBarTest_Vertical
+        self.FoldPanelBarTest_Horizontal = FoldPanelBarTest_Horizontal
+
+        self.Bind(wx.EVT_MENU, self.OnQuit, id=FoldPanelBarTest_Quit)
+        self.Bind(wx.EVT_MENU, self.OnAbout, id=FoldPanelBarTest_About)
+        self.Bind(wx.EVT_MENU, self.OnOrientation, id=FoldPanelBarTest_Horizontal)
+        self.Bind(wx.EVT_MENU, self.OnOrientation, id=FoldPanelBarTest_Vertical)
+
+        value = wx.MenuBar()
+        value.Append(menuFile, "&File")
+        value.Append(helpMenu, "&Help")
+
+        return value
+
+
+    def OnOrientation(self, event):
+        self.CreateFoldBar(event.GetId() == self.FoldPanelBarTest_Vertical)
+
+
+    def OnQuit(self, event):
+        # True is to force the frame to close
+        self.Close(True)
+
+
+    def OnAbout(self, event):
+
+        msg = "This is the about dialog of the FoldPanelBarTest application.\n\n" + \
+              "Welcome To wxPython " + wx.VERSION_STRING + "!!"
+        dlg = wx.MessageDialog(self, msg, "About FoldPanelBarTest",
+                               wx.OK | wx.ICON_INFORMATION)
+        dlg.ShowModal()
+        dlg.Destroy()
+
+
+    def OnCollapseMe(self, event):
+
+        item = self.pnl.GetFoldPanel(0)
+        self.pnl.Collapse(item)
+
+    def OnExpandMe(self, event):
+
+        self.pnl.Expand(self.pnl.GetFoldPanel(0))
+        self.pnl.Collapse(self.pnl.GetFoldPanel(1))
+
+
+    
+# ----------------------------------------------------------------------------
+# NotCollapsed Implementation
+# ----------------------------------------------------------------------------
+
+class NotCollapsed(wx.Frame):
+    def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
+                 size=(400,300), style=wx.DEFAULT_FRAME_STYLE):
+
+        wx.Frame.__init__(self, parent, id, title, pos, size, style)
+        
+        self.SetIcon(GetMondrianIcon())
+        self.SetMenuBar(self.CreateMenuBar())
+
+        self.statusbar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
+        self.statusbar.SetStatusWidths([-4, -3])
+        self.statusbar.SetStatusText("Andrea Gavana @ 23 Mar 2005", 0)
+        self.statusbar.SetStatusText("Welcome to wxPython!", 1)
+
+        pnl = fpb.FoldPanelBar(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
+                           fpb.FPB_DEFAULT_STYLE | fpb.FPB_VERTICAL)
+
+        item = pnl.AddFoldPanel("Test Me", collapsed=False)
+        
+        button1 = wx.Button(item, wx.ID_ANY, "Collapse Me")
+        
+        pnl.AddFoldPanelWindow(item, button1, fpb.FPB_ALIGN_LEFT)
+        pnl.AddFoldPanelSeparator(item)
+        
+        button1.Bind(wx.EVT_BUTTON, self.OnCollapseMe)
+
+        item = pnl.AddFoldPanel("Test Me Too!", collapsed=True)
+        button2 = wx.Button(item, wx.ID_ANY, "Expand First One")
+        pnl.AddFoldPanelWindow(item, button2, fpb.FPB_ALIGN_LEFT)
+        pnl.AddFoldPanelSeparator(item)
+
+        button2.Bind(wx.EVT_BUTTON, self.OnExpandMe)
+        
+        newfoldpanel = FoldTestPanel(item, wx.ID_ANY)
+        pnl.AddFoldPanelWindow(item, newfoldpanel)
+
+        pnl.AddFoldPanelSeparator(item)
+
+        pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),
+                               fpb.FPB_ALIGN_LEFT, fpb.FPB_DEFAULT_SPACING, 20)
+
+        item = pnl.AddFoldPanel("Some Opinions ...", collapsed=False)
+        pnl.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "I Like This"))
+        pnl.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "And Also This"))
+        pnl.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "And Gimme This Too"))
+
+        pnl.AddFoldPanelSeparator(item)
+
+        pnl.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "Check This Too If You Like"))
+        pnl.AddFoldPanelWindow(item, wx.CheckBox(item, wx.ID_ANY, "What About This"))
+
+        item = pnl.AddFoldPanel("Choose One ...", collapsed=False)
+        pnl.AddFoldPanelWindow(item, wx.StaticText(item, wx.ID_ANY, "Enter Your Comment"))
+        pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),
+                               fpb.FPB_ALIGN_WIDTH, fpb.FPB_DEFAULT_SPACING, 20, 20)
+        self.pnl = pnl
+
+
+    def CreateMenuBar(self):
+
+        FoldPanelBarTest_Quit = wx.NewId()
+        FoldPanelBarTest_About = wx.NewId()
+        
+        menuFile = wx.Menu()
+        menuFile.Append(FoldPanelBarTest_Quit, "E&xit\tAlt-X", "Quit This Program")
+
+        helpMenu = wx.Menu()
+        helpMenu.Append(FoldPanelBarTest_About, "&About...\tF1", "Show About Dialog")
+
+        self.Bind(wx.EVT_MENU, self.OnQuit, id=FoldPanelBarTest_Quit)
+        self.Bind(wx.EVT_MENU, self.OnAbout, id=FoldPanelBarTest_About)
+
+        value = wx.MenuBar()
+        value.Append(menuFile, "&File")
+        value.Append(helpMenu, "&Help")
+
+        return value
+
+
+    # Event Handlers
+
+    def OnQuit(self, event):
+
+        # True is to force the frame to close
+        self.Close(True)
+
+
+    def OnAbout(self, event):
+
+        msg = "This is the about dialog of the FoldPanelBarTest application.\n\n" + \
+              "Welcome To wxPython " + wx.VERSION_STRING + "!!"
+        dlg = wx.MessageDialog(self, msg, "About FoldPanelBarTest",
+                               wx.OK | wx.ICON_INFORMATION)
+        dlg.ShowModal()
+        dlg.Destroy()
+
+
+    def OnCollapseMe(self, event):
+
+        item = self.pnl.GetFoldPanel(0)
+        self.pnl.Collapse(item)
+
+    def OnExpandMe(self, event):
+
+        self.pnl.Expand(self.pnl.GetFoldPanel(0))
+        self.pnl.Collapse(self.pnl.GetFoldPanel(1))
+
+
+#---------------------------------------------------------------------------
+#---------------------------------------------------------------------------
+
+class TestPanel(wx.Panel):
+    def __init__(self, parent, log):
+        self.log = log
+        wx.Panel.__init__(self, parent, -1)
+
+        vsizer = wx.BoxSizer(wx.VERTICAL)
+        b = wx.Button(self, -1, "FoldPanelBar Extended Demo")
+        vsizer.Add(b, 0, wx.ALL, 5)
+        self.Bind(wx.EVT_BUTTON, self.OnButton1, b)
+
+        b = wx.Button(self, -1, "FoldPanelBar Collapsed Demo")
+        vsizer.Add(b, 0, wx.ALL, 5)
+        self.Bind(wx.EVT_BUTTON, self.OnButton2, b)
+
+        b = wx.Button(self, -1, "FoldPanelBar NotCollapsed Demo")
+        vsizer.Add(b, 0, wx.ALL, 5)
+        self.Bind(wx.EVT_BUTTON, self.OnButton3, b)
+
+        bdr = wx.BoxSizer()
+        bdr.Add(vsizer, 0, wx.ALL, 50)
+        self.SetSizer(bdr)
+
+    def OnButton1(self, evt):
+        frame = Extended(self, title="FoldPanelBar Extended Demo")
+        frame.Show()
+
+    def OnButton2(self, evt):
+        frame = Collapsed(self, title="FoldPanelBar Collapsed Demo")
+        frame.Show()
+
+    def OnButton3(self, evt):
+        frame = NotCollapsed(self, title="FoldPanelBar NotCollapsed Demo")
+        frame.Show()
+    
+
+#---------------------------------------------------------------------------
+
+
+def runTest(frame, nb, log):
+    win = TestPanel(nb, log)
+    return win
+
+
+#---------------------------------------------------------------------------
+
+
+overview = fpb.__doc__
+
+
+if __name__ == '__main__':
+    import sys,os
+    import run
+    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
+
index 4938824bf898b86f0660477e15e9413c0f365d14..7fbad495e48e58217aefc16f26411605d1614565 100644 (file)
@@ -47,10 +47,7 @@ import images
 _treeList = [
     # new stuff
     ('Recent Additions/Updates', [
-        'StandardPaths',
-        'MediaCtrl',
-        'DatePickerCtrl',
-        'MouseGestures',
+        'FoldPanelBar',
         ]),
 
     # managed windows == things with a (optional) caption you can close
@@ -154,6 +151,7 @@ _treeList = [
         'FileBrowseButton',
         'FloatBar',  
         'FloatCanvas',
+        'FoldPanelBar',
         'HtmlWindow',
         'IntCtrl',
         'MediaCtrl',
index b0305246c2ea452dfb927b21efcc0a868131b30e..2de2a1d91dd525a075c5693f42b7ac8525d446ff 100644 (file)
@@ -34,6 +34,21 @@ end of dragging and not after each CHANGING event (modified patch
 wx.glcanvas.GLCanvas: applied patch fixing problems with X server
 crash when using nVidia cards (patch 1155132)
 
+wx.lib.mixins.listctrl: Patches from Toni Brkic:
+   * Bugfix for TextEditMixin when the view can't be scrolled
+   * Enhancement for ListCtrlAutoWidthMixin, allowing it to manage 
+     the width of any column.
+
+wxMac: removal and reusing toolbar tools like the other platforms is
+now possible.
+
+wxMac: Correct radio tool selection after calling Realize a 2nd time.
+
+wxMSW: Applied patch #1166587, removes all flicker from wx.StaticBox
+
+Added wx.lib.foldpanelbar, Andrea Gavana's port of Jorgen Bodde's C++
+wxFoldPanelBar classes to Python.
+
 
 
 
diff --git a/wxPython/wx/lib/foldpanelbar.py b/wxPython/wx/lib/foldpanelbar.py
new file mode 100644 (file)
index 0000000..abbce9a
--- /dev/null
@@ -0,0 +1,1866 @@
+# --------------------------------------------------------------------------- #
+# FOLDPANELBAR wxPython IMPLEMENTATION
+# Ported From Jorgen Bodde & Julian Smart (Extended Demo) C++ Code By:
+#
+# Andrea Gavana, @ 23 Mar 2005
+# Latest Revision: 28 Mar 2005, 22.30 CET
+#
+#
+# TODO List
+#
+# All The C++ TODOs Are Still Alive. I Am Not Able to Read Jorges's Mind
+# So I Don't Really Know What Will Be The New Features/Additions He Will
+# Make On His Code. At The Moment They Are:
+#
+# 1. OnPaint Function In CaptionBar Class:
+# TODO: Maybe First A Memory Dc Should Draw All, And Then Paint It On The
+# Caption. This Way A Flickering Arrow During Resize Is Not Visible.
+#
+# 2. OnChar Function In CaptionBar Class:
+# TODO: This Is Easy To Do But I Don't Have Any Useful Idea On Which Kind
+# Of Features To Add. Does Anyone Have An Intelligent Idea?
+#
+# 3. AddFoldPanelWindow Function In FoldPanelBar Class:
+# TODO: Take Old And New Heights, And If Difference, Reposition All The
+# Lower Panels. This Is Because The User Can Add New wxWindow Controls
+# Somewhere In Between When Other Panels Are Already Present.
+# Don't Know What It Means. Probably Is My Poor English...
+#
+# 4. OnSizePanel Function In FoldPanelBar Class:
+# TODO: A Smart Way To Check Wether The Old - New Width Of The
+# Panel Changed, If So No Need To Resize The Fold Panel Items
+#
+# 5. Implementing Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD
+# TODO: Jorgen Has Left Undone These Jobs. I Don't Really Get What They
+# Should Supposed To Do, So If Someone Could Enlight Me, Please Let Me Know.
+#
+#
+# For The Original TODO List From Jorgen, Please Refer To:
+# http://www.solidsteel.nl/jorg/components/foldpanel/wxFoldPanelBar.php#todo_list
+#
+#
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@agip.it
+# andrea_gavan@tin.it
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+# --------------------------------------------------------------------------- #
+
+
+"""Description:
+
+The FoldPanelBar is a control that contains multiple panels (FoldPanel items)
+that can be expanded or collapsed. The captionbar of the FoldPanel can be
+customized by setting it to a horizontal gradient style, vertical gradient style,
+a single color, a rectangle or filled rectangle. The FoldPanel items can be
+collapsed in place or to the bottom of the control. The wxWindow derived controls
+can be added dynamically, and separated by separator lines. 
+FoldPanelBar is freeware and distributed under the wxPython license. 
+   
+- How does it work:
+
+The internals of the FoldPanelBar is a list of FoldPanelItem objects. Through
+the reference of FoldPanel these panels can be controlled by adding new controls
+to a FoldPanel or adding new FoldPanels to the FoldPanelBar. 
+The CaptionBar fires events to the parent (container of all panel items) when a
+sub-panel needs resizing (either folding or expanding). The fold or expand process
+is simply a resize of the panel so it looks like all controls on it are gone. All
+controls are still child of the FoldPanel they are located on. If they don't
+handle the event (and they won't) then the owner of the FoldPanelBar gets the
+events. This is what you need to handle the controls. There isn't much to it just
+a lot of calculations to see what panel belongs where. There are no sizers
+involved in the panels, everything is purely x-y positioning. 
+
+
+- What can it do and what not?
+
+    a) What it can do:
+        Run-time addition of panels (no deletion just yet) 
+        Run time addition of controls to the panel (it will be resized accordingly)
+        Creating panels in collapsed mode or expanded mode 
+        Various modes of caption behaviour and filling to make it more appealing 
+        Panels can be folded and collapsed (or all of them) to allow more space
+        
+    b) What it cannot do:
+
+        Selection of a panel like in a list ctrl 
+        Dragging and dropping the panels 
+        Re-ordering the panels (not yet)  
+
+- Supported platforms
+
+FoldPanelBar is supported on the following platforms: 
+Windows (Verified on Windows XP, 2000)
+Linux/Unix (GTK2) (Thanks To Toni Brkic And Robin Dunn)
+Mac OSX (Thanks To Robin Dunn For The CaptionBar Size Patch)
+
+
+Latest Revision: Andrea Gavana @ 30 Mar 2005, 22.30 CET
+
+"""
+
+import wx
+
+#----------------------------------------------------------------------
+# Collapsed And Expanded Bitmap Images
+# Created With img2py.py 
+#----------------------------------------------------------------------
+
+def GetCollapsedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x007IDAT8\x8dcddbf\xa0\x040Q\xa4{\xf0\x1b\xf0\xff\xdf\xdf\xff\x03\xe7\
+\x02\x98\xed\x84\\A\x1b\x17\xa0\xdb\x8a\xcf\x15\xd4w\x01.\xdbp\x89S\xec\x02\
+\xc6\xd1\xbc\xc0\x00\x00\x9a\xf5\x1b\xfa\xf9m$?\x00\x00\x00\x00IEND\xaeB`\
+\x82' 
+
+def GetCollapsedIconBitmap():
+    return wx.BitmapFromImage(GetCollapsedIconImage())
+
+def GetCollapsedIconImage():
+    import  cStringIO
+    stream = cStringIO.StringIO(GetCollapsedIconData())
+    return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+def GetExpandedIconData():
+    return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
+\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
+\x00\x00BIDAT8\x8dcddbf\xa0\x040Q\xa4{P\x18\xc0\x82.\xf0\xff\xdf\xdf\xff\xb8\
+\x143213R\xdd\x05\x18\x06`\xb3\x05\x9f8m\x02\x11\xdd6\\\xb6\xd3\xce\x05\xc8\
+\xb6\xe2\xb3\x9d*.`\x1c\xcd\x0b\x0c\x00\x9e\xbc\x04W\x19\xcfa\xb5\x00\x00\
+\x00\x00IEND\xaeB`\x82' 
+
+def GetExpandedIconBitmap():
+    return wx.BitmapFromImage(GetExpandedIconImage())
+
+def GetExpandedIconImage():
+    import  cStringIO
+    stream = cStringIO.StringIO(GetExpandedIconData())
+    return wx.ImageFromStream(stream)
+
+#----------------------------------------------------------------------
+
+#----------------------------------------------------------------------
+# FOLDPANELBAR Starts Here
+#----------------------------------------------------------------------
+
+# CAPTIONBAR STYLES
+#
+#- CAPTIONBAR_GRADIENT_V: Draws a vertical gradient from top to bottom
+#- CAPTIONBAR_GRADIENT_H: Draws a horizontal gradient from left to right
+#- CAPTIONBAR_SINGLE: Draws a single filled rectangle to draw the caption
+#- CAPTIONBAR_RECTANGLE: Draws a single colour with a rectangle around the caption
+#- CAPTIONBAR_FILLED_RECTANGLE: Draws a filled rectangle and a border around it
+
+CAPTIONBAR_NOSTYLE            = 0
+CAPTIONBAR_GRADIENT_V         = 1
+CAPTIONBAR_GRADIENT_H         = 2
+CAPTIONBAR_SINGLE             = 3
+CAPTIONBAR_RECTANGLE          = 4
+CAPTIONBAR_FILLED_RECTANGLE   = 5
+
+FPB_EXTRA_X = 10
+FPB_EXTRA_Y = 4
+
+# pixels of the bmp to be aligned from the right filled with space
+FPB_BMP_RIGHTSPACE = 2
+
+# Not yet supported but added for future reference. Single fold forces
+# other panels to close when they are open, and only opens the current panel.
+# This will allow the open panel to gain the full size left in the client area
+FPB_SINGLE_FOLD = 0x0001
+
+# All panels are stacked to the bottom. When they are expanded again they
+# show up at the top
+FPB_COLLAPSE_TO_BOTTOM = 0x0002
+
+# Not yet supported, but added for future reference. Single fold plus panels
+# will be stacked at the bottom
+FPB_EXCLUSIVE_FOLD = FPB_SINGLE_FOLD | FPB_COLLAPSE_TO_BOTTOM
+
+# Orientation Flag 
+FPB_HORIZONTAL = wx.HORIZONTAL
+FPB_VERTICAL = wx.VERTICAL  
+
+# Default Extrastyle of the FoldPanelBar 
+FPB_DEFAULT_EXTRASTYLE = 0
+# Default style of the FoldPanelBar 
+FPB_DEFAULT_STYLE = wx.TAB_TRAVERSAL | wx.NO_BORDER
+
+# FoldPanelItem default settings
+FPB_ALIGN_LEFT = 0 
+FPB_ALIGN_WIDTH = 1
+
+FPB_DEFAULT_LEFTSPACING = 5
+FPB_DEFAULT_RIGHTSPACING = 10
+FPB_DEFAULT_SPACING = 8
+
+FPB_DEFAULT_LEFTLINESPACING = 2
+FPB_DEFAULT_RIGHTLINESPACING = 2
+
+
+# ------------------------------------------------------------------------------ #
+# class CaptionBarStyle
+#    This class encapsulates the styles you wish to set for the CaptionBar
+#    (this is the part of the FoldPanel where the caption is displayed). It can
+#    either be applied at creation time be reapplied when styles need to be
+#    changed.
+#
+#    At construction time, all styles are set to their default transparency.
+#    This means none of the styles will be applied to the CaptionBar in question,
+#    meaning it will be created using the default internals. When setting i.e
+#    the color, font or panel style, these styles become active to be used.
+# ------------------------------------------------------------------------------ #
+
+class CaptionBarStyle:
+
+    def __init__(self):
+        """ Default constructor for this class."""
+        
+        self.ResetDefaults()
+
+
+    def ResetDefaults(self):
+        """ Resets Default CaptionBarStyle."""
+        
+        self._firstColourUsed = False
+        self._secondColourUsed = False
+        self._textColourUsed = False
+        self._captionFontUsed = False
+        self._captionStyleUsed = False
+        self._captionStyle = CAPTIONBAR_GRADIENT_V
+
+
+    # ------- CaptionBar Font -------
+    
+    def SetCaptionFont(self, font):
+        """
+        Sets font for the caption bar.
+
+        If this is not set, the font property is undefined and will not
+        be used. Use CaptionFontUsed() to check if this style is used.
+        """
+        
+        self._captionFont = font
+        self._captionFontUsed = True
+
+
+    def CaptionFontUsed(self):
+        """ Checks if the caption bar font is set. """
+        
+        return self._captionFontUsed
+
+
+    def GetCaptionFont(self):
+        """
+        Returns the font for the caption bar.
+
+        Please be warned this will result in an assertion failure when
+        this property is not previously set.
+        See also SetCaptionFont(), CaptionFontUsed()
+        """
+        
+        return self._captionFont
+
+
+    # ------- First Colour -------
+    
+    def SetFirstColour(self, colour):
+        """
+        Sets first colour for the caption bar.
+
+        If this is not set, the colour property is undefined and will not
+        be used. Use FirstColourUsed() to check if this style is used.
+        """
+        
+        self._firstColour = colour
+        self._firstColourUsed = True
+
+
+    def FirstColourUsed(self):
+        """ Checks if the first colour of the caption bar is set."""
+        
+        return self._firstColourUsed
+
+
+    def GetFirstColour(self):
+        """
+        Returns the first colour for the caption bar.
+
+        Please be warned this will result in an assertion failure
+        when this property is not previously set.
+        See also SetCaptionFirstColour(), CaptionFirstColourUsed()
+        """
+        
+        return self._firstColour
+
+
+    # ------- Second Colour -------
+    
+    def SetSecondColour(self, colour):
+        """
+        Sets second colour for the caption bar.
+
+        If this is not set, the colour property is undefined and will not
+        be used. Use SecondColourUsed() to check if this style is used.
+        """
+        
+        self._secondColour = colour
+        self._secondColourUsed = True
+
+
+    def SecondColourUsed(self):
+        """ Checks if the second colour of the caption bar is set."""
+        
+        return self._secondColourUsed
+
+    def GetSecondColour(self):
+        """
+        Returns the second colour for the caption bar.
+
+        Please be warned this will result in an assertion failure
+        when this property is not previously set.
+        See also SetCaptionSecondColour(), CaptionSecondColourUsed()
+        """
+        
+        return self._secondColour
+
+
+    # ------- Caption Text Colour -------
+    
+    def SetCaptionColour(self, colour):
+        """
+        Sets caption colour for the caption bar.
+
+        If this is not set, the colour property is undefined and will not
+        be used. Use CaptionColourUsed() to check if this style is used.
+        """
+        
+        self._textColour = colour
+        self._textColourUsed = True
+
+
+    def CaptionColourUsed(self):
+        """ Checks if the caption colour of the caption bar is set."""
+        
+        return self._textColourUsed
+
+
+    def GetCaptionColour(self):
+        """
+        Returns the caption colour for the caption bar.
+
+        Please be warned this will result in an assertion failure
+        when this property is not previously set.
+        See also SetCaptionColour(), CaptionColourUsed()
+        """
+        
+        return self._textColour
+
+
+    # ------- CaptionStyle  -------
+    
+    def SetCaptionStyle(self, style):
+        """
+        Sets caption style for the caption bar.
+
+        If this is not set, the property is undefined and will not
+        be used. Use CaptionStyleUsed() to check if this style is used.
+        The following styles can be applied:
+            - CAPTIONBAR_GRADIENT_V: Draws a vertical gradient from top to bottom
+            - CAPTIONBAR_GRADIENT_H: Draws a horizontal gradient from left to right
+            - CAPTIONBAR_SINGLE: Draws a single filled rectangle to draw the caption
+            - CAPTIONBAR_RECTANGLE: Draws a single colour with a rectangle around the caption
+            - CAPTIONBAR_FILLED_RECTANGLE: Draws a filled rectangle and a border around it
+        """
+    
+        self._captionStyle = style
+        self._captionStyleUsed = True
+        
+
+    def CaptionStyleUsed(self):
+        """ Checks if the caption style of the caption bar is set."""
+        
+        return self._captionStyleUsed
+
+
+    def GetCaptionStyle(self):
+        """
+        Returns the caption style for the caption bar.
+        
+        Please be warned this will result in an assertion failure
+        when this property is not previously set.
+        See also SetCaptionStyle(), CaptionStyleUsed()
+        """
+        
+        return self._captionStyle
+
+
+#-----------------------------------#
+#        CaptionBarEvent
+#-----------------------------------#
+wxEVT_CAPTIONBAR = wx.NewEventType()
+EVT_CAPTIONBAR = wx.PyEventBinder(wxEVT_CAPTIONBAR, 0)
+
+
+# ---------------------------------------------------------------------------- #
+# class CaptionBarEvent
+#    This event will be sent when a EVT_CAPTIONBAR is mapped in the parent.
+#    It is to notify the parent that the bar is now in collapsed or expanded
+#    state. The parent should re-arrange the associated windows accordingly
+# ---------------------------------------------------------------------------- #
+
+class CaptionBarEvent(wx.PyCommandEvent):
+    
+    def __init__(self, evtType):
+        """ Default Constructor For This Class."""
+        
+        wx.PyCommandEvent.__init__(self, evtType)
+
+        
+    def GetFoldStatus(self):
+        """ Returns Wether The Bar Is Expanded Or Collapsed. True Means Expanded."""
+        
+        return not self._bar.IsCollapsed()
+
+
+    def GetBar(self):
+        """ Returns The CaptionBar Selected."""
+        
+        return self._bar
+
+
+    def SetTag(self, tag):
+        """ Assign A Tag To The Selected CaptionBar."""
+        
+        self._tag = tag
+
+
+    def GetTag(self):
+        """ Returns The Tag Assigned To The Selected CaptionBar."""
+        
+        return self._tag
+
+
+    def SetBar(self, bar):
+        """
+        Sets The Bar Associated With This Event.
+
+        Should Not Used By Any Other Then The Originator Of The Event.
+        """
+        
+        self._bar = bar
+
+
+# -------------------------------------------------------------------------------- #
+# class CaptionBar
+#    This class is a graphical caption component that consists of a caption and
+#    a clickable arrow.
+#
+#    The CaptionBar fires an event EVT_CAPTIONBAR which is a CaptionBarEvent.
+#    This event can be caught and the parent window can act upon the collapsed
+#    or expanded state of the bar (which is actually just the icon which changed).
+#    The parent panel can reduce size or expand again.
+# -------------------------------------------------------------------------------- #
+
+class CaptionBar(wx.Window):
+
+    # Define Empty CaptionBar Style
+    EmptyCaptionBarStyle = CaptionBarStyle()
+    
+    def __init__(self, parent, id, pos, size, caption="",
+                 foldIcons=None, cbstyle=EmptyCaptionBarStyle,
+                 rightIndent=FPB_BMP_RIGHTSPACE,
+                 iconWidth=16, iconHeight=16, collapsed=False):
+        """ Default Class Constructor."""
+        
+        wx.Window.__init__(self, parent, wx.ID_ANY, pos=wx.DefaultPosition,
+                           size=(20,20), style=wx.NO_BORDER)
+
+        self._controlCreated = False
+        self._collapsed = collapsed
+        self.ApplyCaptionStyle(cbstyle, True)
+
+        if foldIcons is None:
+            foldIcons = wx.ImageList(16, 16)
+
+            bmp = GetExpandedIconBitmap()
+            foldIcons.Add(bmp)
+            bmp = GetCollapsedIconBitmap()
+            foldIcons.Add(bmp)
+
+        # set initial size
+        if foldIcons:
+            assert foldIcons.GetImageCount() > 1
+            iconWidth, iconHeight = foldIcons.GetSize(0)
+
+        self._caption = caption
+        self._foldIcons = foldIcons
+        self._style = cbstyle
+        self._rightIndent = rightIndent
+        self._iconWidth = iconWidth
+        self._iconHeight = iconHeight
+        self._oldSize = wx.Size(20,20)
+
+        self._controlCreated = True
+
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)
+        self.Bind(wx.EVT_CHAR, self.OnChar)
+        
+
+    def ApplyCaptionStyle(self, cbstyle=EmptyCaptionBarStyle, applyDefault=True):
+        """ Applies the style defined in cbstyle to the CaptionBar."""
+        
+        newstyle = cbstyle
+        
+        if applyDefault:
+
+            # get first colour from style or make it default
+            if not newstyle.FirstColourUsed():
+                newstyle.SetFirstColour(wx.WHITE)
+
+            # get second colour from style or make it default
+            if not newstyle.SecondColourUsed():
+                # make the second colour slightly darker then the background
+                color = self.GetParent().GetBackgroundColour()
+                r, g, b = int(color.Red()), int(color.Green()), int(color.Blue())
+                color = ((r >> 1) + 20, (g >> 1) + 20, (b >> 1) + 20)
+                newstyle.SetSecondColour(wx.Colour(color[0], color[1], color[2]))
+
+            # get text colour
+            if not newstyle.CaptionColourUsed():
+                newstyle.SetCaptionColour(wx.BLACK)
+
+            # get font colour
+            if not newstyle.CaptionFontUsed():
+                newstyle.SetCaptionFont(self.GetParent().GetFont())
+
+            # apply caption style
+            if not newstyle.CaptionStyleUsed():
+                newstyle.SetCaptionStyle(CAPTIONBAR_GRADIENT_V)
+
+        self._style = newstyle
+        
+
+    def SetCaptionStyle(self, cbstyle=EmptyCaptionBarStyle, applyDefault=True):
+        """
+        Sets CaptionBar styles with CapionBarStyle class.
+
+        All styles that are actually set, are applied. If you set applyDefault
+        to True, all other (not defined) styles will be set to default. If it
+        is False, the styles which are not set in the CaptionBarStyle will be
+        ignored.
+        """
+        
+        self.ApplyCaptionStyle(cbstyle, applyDefault)
+        self.Refresh()
+
+    
+    def GetCaptionStyle(self):
+        """
+        Returns the current style of the captionbar in a CaptionBarStyle class.
+
+        This can be used to change and set back the changes.
+        """
+        
+        return self._style
+
+
+    def IsCollapsed(self):
+        """
+        Returns wether the status of the bar is expanded or collapsed. """
+        
+        return self._collapsed
+    
+
+    def SetRightIndent(self, pixels):
+        """
+        Sets the amount of pixels on the right from which the bitmap is trailing.
+
+        If this is 0, it will be drawn all the way to the right, default is
+        equal to FPB_BMP_RIGHTSPACE. Assign this before assigning an image
+        list to prevent a redraw.
+        """
+
+        assert pixels >= 0
+        self._rightIndent = pixels
+        if self._foldIcons:
+            self.Refresh()
+
+
+    def Collapse(self):
+        """
+        This sets the internal state / representation to collapsed.
+
+        This does not trigger a CaptionBarEvent to be sent to the parent.
+        """
+        
+        self._collapsed = True
+        self.RedrawIconBitmap()
+
+
+    def Expand(self):
+        """
+        This sets the internal state / representation to expanded.
+
+        This does not trigger a CaptionBarEvent to be sent to the parent.
+        """
+        
+        self._collapsed = False
+        self.RedrawIconBitmap()
+        
+
+    def SetBoldFont(self):
+        """ Sets the CaptionBarFont weight to BOLD."""
+        
+        self.GetFont().SetWeight(wx.BOLD)
+
+
+    def SetNormalFont(self):
+        """ Sets the CaptionBarFont weight to NORMAL."""
+        
+        self.GetFont().SetWeight(wx.NORMAL)
+
+
+    def IsVertical(self):
+        """
+        Returns wether the CaptionBar Has Default Orientation Or Not.
+
+        Default is vertical.
+        """
+        
+        fld = self.GetParent().GetGrandParent()
+        if isinstance(fld, FoldPanelBar):
+            return self.GetParent().GetGrandParent().IsVertical()
+        else:
+            raise "ERROR: Wrong Parent " + repr(fld)
+
+        
+    def OnPaint(self, event):
+        """ The paint event for flat or gradient fill. """
+        
+        if not self._controlCreated:
+            event.Skip()
+            return
+        
+        dc = wx.PaintDC(self)
+        wndRect = self.GetRect()
+        vertical = self.IsVertical()
+
+        # TODO: Maybe first a memory DC should draw all, and then paint it on
+        # the caption. This way a flickering arrow during resize is not visible
+        
+        self.FillCaptionBackground(dc)
+        dc.SetFont(self._style.GetCaptionFont())
+
+        if vertical:
+            dc.DrawText(self._caption, 4, FPB_EXTRA_Y/2)
+        else:
+            dc.DrawRotatedText(self._caption, FPB_EXTRA_Y/2,
+                               wndRect.GetBottom() - 4, 90)
+
+        # draw small icon, either collapsed or expanded
+        # based on the state of the bar. If we have any bmp's
+
+        if self._foldIcons:
+
+            index = self._collapsed
+            
+            if vertical:
+                drw = wndRect.GetRight() - self._iconWidth - self._rightIndent
+                self._foldIcons.Draw(index, dc, drw,
+                                     (wndRect.GetHeight() - self._iconHeight)/2,
+                                     wx.IMAGELIST_DRAW_TRANSPARENT)
+            else:
+                self._foldIcons.Draw(index, dc,
+                                     (wndRect.GetWidth() - self._iconWidth)/2,
+                                     self._rightIndent, wx.IMAGELIST_DRAW_TRANSPARENT)
+
+##        event.Skip()
+        
+
+    def FillCaptionBackground(self, dc):
+        """ Fills the background of the caption with either a gradient or a solid color. """
+
+        style = self._style.GetCaptionStyle()
+
+        if style == CAPTIONBAR_GRADIENT_V:
+            if self.IsVertical():
+                self.DrawVerticalGradient(dc, self.GetRect())
+            else:
+                self.DrawHorizontalGradient(dc, self.GetRect())
+
+        elif style == CAPTIONBAR_GRADIENT_H:
+            if self.IsVertical():
+                self.DrawHorizontalGradient(dc, self.GetRect())
+            else:
+                self.DrawVerticalGradient(dc, self.GetRect())
+            
+        elif style == CAPTIONBAR_SINGLE:
+            self.DrawSingleColour(dc, self.GetRect())
+        elif style == CAPTIONBAR_RECTANGLE or style == CAPTIONBAR_FILLED_RECTANGLE:
+            self.DrawSingleRectangle(dc, self.GetRect())
+        else:
+            raise "STYLE Error: Undefined Style Selected: " + repr(style)
+
+
+    def OnMouseEvent(self, event):
+        """
+        Catches the mouse click-double click.
+        
+        If clicked on the arrow (single) or double on the caption we change state
+        and an event must be fired to let this panel collapse or expand.
+        """
+        
+        send_event = False
+
+        if event.LeftDown() and self._foldIcons:
+
+            pt = event.GetPosition()
+            rect = self.GetRect()
+            vertical = self.IsVertical()
+
+            drw = (rect.GetWidth() - self._iconWidth - self._rightIndent)
+            if vertical and pt.x > drw or not vertical and \
+               pt.y < (self._iconHeight + self._rightIndent):
+                send_event = True
+
+        elif event.LeftDClick():
+            send_event = True
+
+        # send the collapse, expand event to the parent
+        
+        if send_event:
+            event = CaptionBarEvent(wxEVT_CAPTIONBAR)
+            event.SetBar(self)
+            self.GetEventHandler().ProcessEvent(event)
+            event.Skip()
+        
+
+    def OnChar(self, event):
+        """ Unused Methods. Any Ideas?!?"""
+        
+        # TODO: Anything here?
+        event.Skip()
+
+
+    def DoGetBestSize(self):
+        """ Returns the best size for this panel, based upon the font assigned
+        to this window, and the caption string"""
+        
+        if self.IsVertical():
+            x, y = self.GetTextExtent(self._caption)
+        else:
+            y, x = self.GetTextExtent(self._caption)
+
+        if x < self._iconWidth:
+            x = self._iconWidth
+
+        if y < self._iconHeight:
+            y = self._iconHeight
+
+        # TODO: The extra FPB_EXTRA_X constants should be adjustable as well
+
+        return wx.Size(x + FPB_EXTRA_X, y + FPB_EXTRA_Y)
+
+
+    def DrawVerticalGradient(self, dc, rect):
+        """ Gradient fill from colour 1 to colour 2 with top to bottom. """
+
+        if  rect.height < 1 or rect.width < 1:
+            return
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        # calculate gradient coefficients
+        col2 = self._style.GetSecondColour()
+        col1 = self._style.GetFirstColour()
+
+        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+        flrect = float(rect.height)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+
+        for y in range(rect.y, rect.y + rect.height):
+            currCol = (r1 + rf, g1 + gf, b1 + bf)
+                
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            dc.DrawRectangle(rect.x, rect.y + (y - rect.y), rect.width, rect.height)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+
+    def DrawHorizontalGradient(self, dc, rect):
+        """ Gradient fill from colour 1 to colour 2 with left to right. """
+
+        if rect.height < 1 or rect.width < 1:
+            return
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        # calculate gradient coefficients
+        col2 = self._style.GetSecondColour()
+        col1 = self._style.GetFirstColour()
+
+        r1, g1, b1 = int(col1.Red()), int(col1.Green()), int(col1.Blue())
+        r2, g2, b2 = int(col2.Red()), int(col2.Green()), int(col2.Blue())
+
+        flrect = float(rect.width)
+
+        rstep = float((r2 - r1)) / flrect
+        gstep = float((g2 - g1)) / flrect
+        bstep = float((b2 - b1)) / flrect
+
+        rf, gf, bf = 0, 0, 0
+        
+        for x in range(rect.x, rect.x + rect.width):
+            currCol = (r1 + rf, g1 + gf, b1 + bf)
+                
+            dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+            dc.DrawRectangle(rect.x + (x - rect.x), rect.y, 1, rect.height)
+            rf = rf + rstep
+            gf = gf + gstep
+            bf = bf + bstep
+
+
+    def DrawSingleColour(self, dc, rect):
+        """ Single colour fill. This is the most easy one to find. """
+
+        if rect.height < 1 or rect.width < 1:
+            return
+
+        dc.SetPen(wx.TRANSPARENT_PEN)
+
+        # draw simple rectangle
+        dc.SetBrush(wx.Brush(self._style.GetFirstColour(), wx.SOLID))
+        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
+        
+
+    def DrawSingleRectangle(self, dc, rect):
+        """ Single rectangle. This is the most easy one to find. """
+        
+        if rect.height < 2 or rect.width < 1:
+            return
+
+        # single frame, set up internal fill colour
+
+        if self._style.GetCaptionStyle() == CAPTIONBAR_RECTANGLE:
+            color = self.GetParent().GetBackgroundColour()
+            br = wx.Brush(color, wx.SOLID)
+        else:
+            color = self._style.GetFirstColour()
+            br = wx.Brush(color, wx.SOLID)
+
+        # setup the pen frame
+
+        pen = wx.Pen(self._style.GetSecondColour())
+        dc.SetPen(pen)
+        dc.SetBrush(br)
+        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height - 1)
+
+        bgpen = wx.Pen(self.GetParent().GetBackgroundColour())
+        dc.SetPen(bgpen)
+        dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width,
+                    rect.y + rect.height - 1)
+
+
+    def OnSize(self, event):
+        """ Handles the size events for the CaptionBar."""
+
+        if not self._controlCreated:
+            event.Skip()
+            return
+        
+        size = event.GetSize()
+
+        if self._foldIcons:
+
+            # What I am doing here is simply invalidating the part of the window
+            # exposed. So when I make a rect with as width the newly exposed part,
+            # and the x,y of the old window size origin, I don't need a bitmap
+            # calculation in it, or do I ? The bitmap needs redrawing anyway. 
+            # Leave it like this until I figured it out.
+
+            # set rect to redraw as old bitmap area which is entitled to redraw
+
+            rect = wx.Rect(size.GetWidth() - self._iconWidth - self._rightIndent, 0,
+                           self._iconWidth + self._rightIndent,
+                           self._iconWidth + self._rightIndent)
+            
+            # adjust rectangle when more is slided so we need to redraw all
+            # the old stuff but not all (ugly flickering)
+
+            diffX = size.GetWidth() - self._oldSize.GetWidth()
+            
+            if diffX > 1:
+                
+                # adjust the rect with all the crap to redraw
+
+                rect.SetWidth(rect.GetWidth() + diffX + 10)
+                rect.SetX(rect.GetX() - diffX - 10)
+
+            self.RefreshRect(rect)
+            
+        else:
+            
+            rect = self.GetRect()
+            self.RefreshRect(rect)
+
+        self._oldSize = size
+        
+
+    def RedrawIconBitmap(self):
+        """ Redraws the icons (if they exists). """
+
+        if self._foldIcons:
+        
+            # invalidate the bitmap area and force a redraw
+
+            rect = self.GetRect()
+
+            rect.SetX(rect.GetWidth() - self._iconWidth - self._rightIndent)
+            rect.SetWidth(self._iconWidth + self._rightIndent)
+            self.RefreshRect(rect)
+
+
+# ---------------------------------------------------------------------------------- #
+# class FoldPanelBar
+#    The FoldPanelBar is a class which can maintain a list of collapsable panels.
+#    Once a panel is collapsed, only it's panel bar is visible to the user. This
+#    will provide more space for the other panels, or allow the user to close
+#    panels which are not used often to get the most out of the work area.
+#
+#    This control is easy to use. Simply create it as a child for a panel or
+#    sash window, and populate panels with FoldPanelBar.AddFoldPanel(). Then use
+#    the FoldPanelBar.AddFoldPanelWindow() to add wxWindow derived controls to the
+#    current fold panel. Use FoldPanelBar.AddFoldPanelSeparator() to put separators
+#    between the groups of controls that need a visual separator to group them
+#    together. After all is constructed, the user can fold the panels by
+#    doubleclicking on the bar or single click on the arrow, which will indicate
+#    the collapsed or expanded state.
+# ---------------------------------------------------------------------------------- #
+
+class FoldPanelBar(wx.Panel):
+
+    # Define Empty CaptionBar Style
+    EmptyCaptionBarStyle = CaptionBarStyle()
+    
+    def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=FPB_DEFAULT_STYLE, extraStyle=FPB_DEFAULT_EXTRASTYLE): 
+        """ Default Class Constructor. """
+        
+        self._controlCreated = False
+        self._extraStyle = extraStyle
+        
+        # make sure there is any orientation
+        if style & FPB_HORIZONTAL != FPB_HORIZONTAL:
+            style = style | FPB_VERTICAL
+
+        if style & FPB_HORIZONTAL == 4:
+            self._isVertical = False
+        else:
+            self._isVertical = True
+
+        
+        # create the panel (duh!). This causes a size event, which we are going
+        # to skip when we are not initialised
+
+        wx.Panel.__init__(self, parent, id, pos, size, style)
+
+        # the fold panel area
+
+        self._foldPanel = wx.Panel(self, wx.ID_ANY, pos, size,
+                                   wx.NO_BORDER | wx.TAB_TRAVERSAL)
+
+        self._controlCreated = True
+        self._panels = []
+
+        self.Bind(EVT_CAPTIONBAR, self.OnPressCaption)
+        self.Bind(wx.EVT_SIZE, self.OnSizePanel)
+        
+
+    def AddFoldPanel(self, caption="", collapsed=False, foldIcons=None,
+                     cbstyle=EmptyCaptionBarStyle):
+        """
+        Adds a fold panel to the list of panels.
+
+        If the flag collapsed is set to True, the panel is collapsed initially.
+        The FoldPanel item which is returned, can be used as a reference to
+        perform actions upon the fold panel like collapsing it, expanding it,
+        or deleting it from the list.
+
+        Use this foldpanel to add windows to it. Please consult
+        FoldPanelBar.AddFoldPanelWindow() and
+        FoldPanelBar.AddFoldPanelSeparator() to know how to add wxWindow items
+        to the panels.
+        """
+
+        # create a fold panel item, which is first only the caption.
+        # the user can now add a panel area which will be folded in
+        # when pressed.
+
+        if foldIcons is None:
+            foldIcons = wx.ImageList(16, 16)
+
+            bmp = GetExpandedIconBitmap()
+            foldIcons.Add(bmp)
+            bmp = GetCollapsedIconBitmap()
+            foldIcons.Add(bmp)
+    
+        item = FoldPanelItem(self._foldPanel, -1, caption=caption,
+                             foldIcons=foldIcons,
+                             collapsed=collapsed, cbstyle=cbstyle)
+        
+        pos = 0
+        if len(self._panels) > 0:
+            pos = self._panels[-1].GetItemPos() + self._panels[-1].GetPanelLength()
+
+        item.Reposition(pos)
+        self._panels.append(item)
+
+        return item
+
+
+    def AddFoldPanelWindow(self, panel, window, flags=FPB_ALIGN_WIDTH,
+                           Spacing=FPB_DEFAULT_SPACING,
+                           leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+                           rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+        """
+        Adds a wxWindow derived class to the referenced FoldPanel.
+
+        IMPORTANT: Make the to be created window, child of the FoldPanel. See
+        example that follows. The flags to be used are:
+            - FPB_ALIGN_WIDTH: Which means the wxWindow to be added will be
+              aligned to fit the width of the FoldPanel when it is resized.
+              Very handy for sizer items, buttons and text boxes.
+            - FPB_ALIGN_LEFT: Alligns left instead of fitting the width of
+              the child window to be added. Use either this one or
+              FPB_ALIGN_WIDTH.
+
+        The wxWindow to be added can be slightly indented from left and right
+        so it is more visibly placed in the FoldPanel. Use Spacing > 0 to give
+        the control an y offset from the previous wxWindow added, use leftSpacing
+        to give it a slight indent from the left, and rightSpacing also reserves
+        a little space on the right so the wxWindow can be properly placed in
+        the FoldPanel.
+
+        The following example adds a FoldPanel to the FoldPanelBar and adds two
+        wxWindow derived controls to the FoldPanel:
+
+        # CODE
+
+            # create the FoldPanelBar
+            >>> m_pnl = FoldPanelBar(self, wx.ID_ANY, wx.DefaultPosition,
+                                     wx.DefaultSize, FPB_DEFAULT_STYLE,
+                                     FPB_COLLAPSE_TO_BOTTOM)
+
+            # add a foldpanel to the control. "Test me" is the caption and it is
+            # initially not collapsed.
+            >>> item = m_pnl.AddFoldPanel("Test me", False)
+
+            # now add a button to the fold panel. Mind that the button should be
+            # made child of the FoldPanel and not of the main form.
+            >>> m_pnl.AddFoldPanelWindow(item, wx.Button(item, ID_COLLAPSEME,
+                                        "Collapse Me"))
+
+            # add a separator between the two controls. This is purely a visual
+            # line that can have a certain color and also the indents and width
+            # aligning like a control.
+            >>> m_pnl.AddFoldPanelSeparator(item)
+
+            # now add a text ctrl. Also very easy. Align this on width so that
+            # when the control gets wider the text control also sizes along.
+            >>> m_pnl.AddFoldPanelWindow(item, wx.TextCtrl(item, wx.ID_ANY, "Comment"),
+                                         FPB_ALIGN_WIDTH, FPB_DEFAULT_SPACING, 20)
+
+        # ENDCODE
+        """
+        
+        try:
+            item = self._panels.index(panel)
+        except:
+            raise "ERROR: Invalid Panel Passed To AddFoldPanelWindow: " + repr(panel)
+        
+        panel.AddWindow(window, flags, Spacing, leftSpacing, rightSpacing)
+
+        # TODO: Take old and new height, and if difference, reposition all the lower
+        # panels this is because the user can add new wxWindow controls somewhere in
+        # between when other panels are already present.
+    
+        return 0
+
+
+    def AddFoldPanelSeparator(self, panel, colour=wx.BLACK,
+                              Spacing=FPB_DEFAULT_SPACING,
+                              leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+                              rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+        """
+        Adds a separator line to the current FoldPanel.
+        
+        The seperator is a simple line which is drawn and is no real component.
+        It can be used to separate groups of controls which belong to each other.
+        The colour is adjustable, and it takes the same Spacing, leftSpacing and
+        rightSpacing as AddFoldPanelWindow().
+        """
+        
+        try:
+            item = self._panels.index(panel)
+        except:
+            raise "ERROR: Invalid Panel Passed To AddFoldPanelSeparator: " + repr(panel)
+        
+        panel.AddSeparator(colour, Spacing, leftSpacing, rightSpacing)
+        return 0
+
+
+    def OnSizePanel(self, event):
+        """ Handles the EVT_SIZE method for the FoldPanelBar. """
+
+        # skip all stuff when we are not initialised yet
+
+        if not self._controlCreated:
+            event.Skip()
+            return
+
+        foldrect = self.GetRect()
+
+        # fold panel itself. If too little space,
+        # don't show it
+
+        foldrect.SetX(0)
+        foldrect.SetY(0)
+
+        self._foldPanel.SetSize(foldrect[2:])
+        
+        if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM:
+            rect = self.RepositionCollapsedToBottom()
+            vertical = self.IsVertical()
+            if vertical and rect.GetHeight() > 0 or not vertical and rect.GetWidth() > 0:
+                self.RefreshRect(rect)
+
+        # TODO: A smart way to check wether the old - new width of the
+        # panel changed, if so no need to resize the fold panel items
+
+        self.RedisplayFoldPanelItems()
+    
+
+    def OnPressCaption(self, event):
+        """ Handles the EVT_CAPTIONBAR event in the FoldPanelBar. """
+
+        # act upon the folding or expanding status of the bar
+        # to expand or collapse the panel(s)
+
+        if event.GetFoldStatus():
+            self.Collapse(event.GetTag())
+        else:
+            self.Expand(event.GetTag())
+
+        event.Skip()
+        
+
+    def RefreshPanelsFrom(self, item):
+        """ Refreshes all the panels from given index down to last one. """
+        
+        try:
+            i = self._panels.index(item)
+        except:
+            raise "ERROR: Invalid Panel Passed To RefreshPanelsFrom: " + repr(item)
+        
+        self.Freeze()
+
+        # if collapse to bottom is on, the panels that are not expanded
+        # should be drawn at the bottom. All panels that are expanded
+        # are drawn on top. The last expanded panel gets all the extra space
+
+        if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM:
+        
+            offset = 0
+
+            for panels in self._panels:
+            
+                if panels.IsExpanded():
+                    offset = offset + panels.Reposition(offset)
+        
+            # put all non collapsed panels at the bottom where there is space, 
+            # else put them right behind the expanded ones
+
+            self.RepositionCollapsedToBottom()
+        
+        else:
+        
+            pos = self._panels[i].GetItemPos() + self._panels[i].GetPanelLength()
+            for j in range(i+1, len(self._panels)):
+                pos = pos + self._panels[j].Reposition(pos)
+
+        
+        self.Thaw()
+##        self.Refresh()
+        
+
+    def RedisplayFoldPanelItems(self):
+        """ Resizes the fold panels so they match the width. """
+        
+        # resize them all. No need to reposition
+
+        for panels in self._panels:
+            panels.ResizePanel()
+            panels.Refresh()
+
+
+    def RepositionCollapsedToBottom(self):
+        """
+        Repositions all the collapsed panels to the bottom.
+
+        When it is not possible to align them to the bottom, stick them behind the
+        visible panels. The Rect holds the slack area left between last repositioned
+        panel and the bottom panels. This needs to get a refresh.
+        """
+
+        value = wx.Rect(0,0,0,0)
+        vertical = self.IsVertical()
+
+        # determine wether the number of panels left
+        # times the size of their captions is enough
+        # to be placed in the left over space
+
+        expanded = 0
+        collapsed = 0
+        collapsed, expanded, values = self.GetPanelsLength(collapsed, expanded)
+
+        # if no room stick them behind the normal ones, else
+        # at the bottom
+
+        if (vertical and [self.GetSize().GetHeight()] or \
+            [self.GetSize().GetWidth()])[0] - expanded - collapsed < 0:
+            offset = expanded
+        else:
+
+            # value is the region which is left unpainted
+            # I will send it back as 'slack' so it does not need to
+            # be recalculated.
+
+            value.SetHeight(self.GetSize().GetHeight())
+            value.SetWidth(self.GetSize().GetWidth())
+
+            if vertical:
+                value.SetY(expanded)
+                value.SetHeight(value.GetHeight() - expanded)
+            else:
+                value.SetX(expanded)
+                value.SetWidth(value.GetWidth() - expanded)
+
+            offset = (vertical and [self.GetSize().GetHeight()] or \
+                      [self.GetSize().GetWidth()])[0] - collapsed
+
+
+        # go reposition
+
+        for panels in self._panels:
+            if not panels.IsExpanded():
+                offset = offset + panels.Reposition(offset)
+
+        return value
+
+
+    def GetPanelsLength(self, collapsed, expanded):
+        """
+        Returns the length of the panels that are expanded and collapsed.
+
+        This is useful to determine quickly what size is used to display,
+        and what is left at the bottom (right) to align the collapsed panels.
+        """
+        
+        value = 0
+
+        # assumed here that all the panels that are expanded
+        # are positioned after each other from 0,0 to end.
+
+        for j in range(0, len(self._panels)):
+            offset = self._panels[j].GetPanelLength()
+            value = value + offset
+            if self._panels[j].IsExpanded():
+                expanded = expanded + offset
+            else:
+                collapsed = collapsed + offset
+
+        return collapsed, expanded, value
+
+
+    def Collapse(self, foldpanel):
+        """
+        Collapses the given FoldPanel reference, and updates the foldpanel bar.
+
+        In the FPB_COLLAPSE_TO_BOTTOM style, all collapsed captions are put at
+        the bottom of the control. In the normal mode, they stay where they are.
+        """
+        
+        try:
+            item = self._panels.index(foldpanel)
+        except:
+            raise "ERROR: Invalid Panel Passed To Collapse: " + repr(foldpanel)
+        
+        foldpanel.Collapse()
+        self.RefreshPanelsFrom(foldpanel)
+
+
+    def Expand(self, foldpanel):
+        """
+        Expands the given FoldPanel reference, and updates the foldpanel bar.
+        
+        In the FPB_COLLAPSE_TO_BOTTOM style, they will be removed from the bottom
+        and the order where the panel originally was placed is restored.
+        """
+        
+        foldpanel.Expand()
+        self.RefreshPanelsFrom(foldpanel)
+
+
+    def ApplyCaptionStyle(self, foldpanel, cbstyle):
+        """
+        Sets the style of the caption bar (called CaptionBar) of the FoldPanel.
+
+        The changes are applied immediately. All styles not set in the CaptionBarStyle
+        class are not applied. Use the CaptionBar reference to indicate what captionbar
+        you want to apply the style to. To apply one style to all CaptionBar items, use
+        ApplyCaptionStyleAll()
+        """
+        
+        foldpanel.ApplyCaptionStyle(cbstyle)
+        
+
+    def ApplyCaptionStyleAll(self, cbstyle):
+        """ Sets the style of all the caption bars of the FoldPanel.
+
+        The changes are applied immediately. """
+        for panels in self._panels:
+            self.ApplyCaptionStyle(panels, cbstyle)
+            
+
+    def GetCaptionStyle(self, foldpanel):
+        """
+        Returns the currently used caption style for the FoldPanel.
+
+        It is returned as a CaptionBarStyle class. After modifying it, it can be
+        set again.
+        """
+        
+        return foldpanel.GetCaptionStyle()
+
+
+    def IsVertical(self):
+        """
+        Returns wether the CaptionBar Has Default Orientation Or Not.
+
+        Default is vertical.
+        """
+        
+        return self._isVertical
+
+
+    def GetFoldPanel(self, item):
+        """
+        Returns the panel associated with the index "item".
+
+        See the example at the bottom of the module, especially the events
+        for the "Collapse Me" and "Expand Me" buttons.
+        """
+
+        try:
+            ind = self._panels[item]
+            return self._panels[item]
+        except:
+            raise "ERROR: List Index Out Of Range Or Bad Item Passed: " + repr(item) + \
+                  ". Item Should Be An Integer Between " + repr(0) + " And " + \
+                  repr(len(self._panels))
+
+
+    def GetCount(self):
+        """ Returns the number of panels in the FoldPanelBar. """
+
+        try:
+            return len(self._panels)
+        except:
+            raise "ERROR: No Panels Have Been Added To FoldPanelBar"
+
+        
+
+# --------------------------------------------------------------------------------- #
+# class FoldPanelItem
+#    This class is a child sibling of the FoldPanelBar class. It will contain a
+#    CaptionBar class for receiving of events, and a the rest of the area can be
+#    populated by a wxPanel derived class.
+# --------------------------------------------------------------------------------- #
+
+class FoldPanelItem(wx.Panel):
+
+    # Define Empty CaptionBar Style
+    EmptyCaptionBarStyle = CaptionBarStyle()
+    
+    def __init__(self, parent, id=wx.ID_ANY, caption="", foldIcons=None,
+                 collapsed=False, cbstyle=EmptyCaptionBarStyle):
+        """ Default Class Constructor. """
+        
+        wx.Panel.__init__(self, parent, id, style=wx.CLIP_CHILDREN)
+        self._controlCreated = False
+        self._UserSize = 0
+        self._PanelSize = 0
+        self._LastInsertPos = 0
+        self._itemPos = 0
+        self._userSized = False
+
+        if foldIcons is None:
+            foldIcons = wx.ImageList(16, 16)
+
+            bmp = GetExpandedIconBitmap()
+            foldIcons.Add(bmp)
+            bmp = GetCollapsedIconBitmap()
+            foldIcons.Add(bmp)
+        
+        self._foldIcons = foldIcons
+
+        # create the caption bar, in collapsed or expanded state
+         
+        self._captionBar = CaptionBar(self, wx.ID_ANY, wx.Point(0,0),
+                                      size=wx.DefaultSize, caption=caption,
+                                      foldIcons=foldIcons, cbstyle=cbstyle)
+
+        if collapsed:
+            self._captionBar.Collapse()
+
+        self._controlCreated = True
+
+        # make initial size for component, if collapsed, the
+        # size is determined on the panel height and won't change
+    
+        size = self._captionBar.GetSize()
+
+        self._PanelSize = (self.IsVertical() and [size.GetHeight()] or \
+                           [size.GetWidth()])[0]
+        
+        self._LastInsertPos = self._PanelSize
+        self._items = []
+
+        self.Bind(EVT_CAPTIONBAR, self.OnPressCaption)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+    def AddWindow(self, window, flags=FPB_ALIGN_WIDTH, Spacing=FPB_DEFAULT_SPACING,
+                  leftSpacing=FPB_DEFAULT_LEFTLINESPACING,
+                  rightSpacing=FPB_DEFAULT_RIGHTLINESPACING):
+        """
+        Adds a window item to the list of items on this panel.
+
+        The flags are FPB_ALIGN_LEFT for a non sizing window element, and
+        FPB_ALIGN_WIDTH for a width aligned item. The Spacing parameter reserves
+        a number of pixels before the window element, and leftSpacing is an indent.
+        rightSpacing is only relevant when the style FPB_ALIGN_WIDTH is chosen.
+        """
+        
+        wi = FoldWindowItem(self, window, Type="WINDOW", flags=flags, Spacing=Spacing,
+                            leftSpacing=leftSpacing, rightSpacing=rightSpacing)
+        
+        self._items.append(wi)
+
+        vertical = self.IsVertical()
+        
+        self._Spacing = Spacing
+        self._leftSpacing = leftSpacing
+        self._rightSpacing = rightSpacing
+
+        xpos = (vertical and [leftSpacing] or [self._LastInsertPos + Spacing])[0]
+        ypos = (vertical and [self._LastInsertPos + Spacing] or [leftSpacing])[0]
+
+        window.SetDimensions(xpos, ypos, -1, -1, wx.SIZE_USE_EXISTING)
+
+        self._LastInsertPos = self._LastInsertPos + wi.GetWindowLength(vertical)
+        self.ResizePanel()
+        
+
+    def AddSeparator(self, colour=wx.BLACK, Spacing=FPB_DEFAULT_SPACING,
+                     leftSpacing=FPB_DEFAULT_LEFTSPACING,
+                     rightSpacing=FPB_DEFAULT_RIGHTSPACING):
+        """
+        Adds a separator item to the list of items on this panel. """
+        
+        wi = FoldWindowItem(self, window=None, Type="SEPARATOR",
+                            flags=FPB_ALIGN_WIDTH, y=self._LastInsertPos,
+                            colour=colour, Spacing=Spacing, leftSpacing=leftSpacing,
+                            rightSpacing=rightSpacing)
+        
+        self._items.append(wi)
+        self._LastInsertPos = self._LastInsertPos + \
+                              wi.GetWindowLength(self.IsVertical())
+        
+        self.ResizePanel()
+
+
+    def Reposition(self, pos):
+        """ Repositions this FoldPanelBar and reports the length occupied for the
+        next FoldPanelBar in the list. """
+        
+        # NOTE: Call Resize before Reposition when an item is added, because the new
+        # size needed will be calculated by Resize. Of course the relative position
+        # of the controls have to be correct in respect to the caption bar
+    
+        self.Freeze()
+
+        vertical = self.IsVertical()
+        xpos = (vertical and [-1] or [pos])[0]
+        ypos = (vertical and [pos] or [-1])[0]
+
+        self.SetDimensions(xpos, ypos, -1, -1, wx.SIZE_USE_EXISTING)
+        self._itemPos = pos
+
+        self.Thaw()
+##        self.Refresh()
+
+        return self.GetPanelLength()
+
+
+    def OnPressCaption(self, event):
+        """ Handles the EVT_CAPTIONBAR event in the FoldPanelItem. """
+        
+        # tell the upper container we are responsible
+        # for this event, so it can fold the panel item
+        # and do a refresh
+
+        event.SetTag(self)
+        event.Skip()
+
+
+    def ResizePanel(self):
+        """ Resizes the panel. """
+        
+        # prevent unnecessary updates by blocking repaints for a sec
+
+        self.Freeze()
+
+        vertical = self.IsVertical()
+        # force this panel to take the width of the parent panel and the y of the
+        # user or calculated width (which will be recalculated by the contents here)
+
+
+        if self._captionBar.IsCollapsed():
+            size = self._captionBar.GetSize()
+            self._PanelSize = (vertical and [size.GetHeight()] or [size.GetWidth()])[0]
+        else:
+            size = self.GetBestSize()
+            self._PanelSize = (vertical and [size.GetHeight()] or [size.GetWidth()])[0]
+
+            if self._UserSize:
+                if vertical:
+                    size.SetHeight(self._UserSize)
+                else:
+                    size.SetWidth(self._UserSize)
+
+        pnlsize = self.GetParent().GetSize()
+
+        if vertical:
+            size.SetWidth(pnlsize.GetWidth())
+        else:
+            size.SetHeight(pnlsize.GetHeight())
+        
+        # resize caption bar
+        xsize = (vertical and [size.GetWidth()] or [-1])[0]
+        ysize = (vertical and [-1] or [size.GetHeight()])[0]
+
+        self._captionBar.SetSize((xsize, ysize))
+
+        # resize the panel
+        self.SetSize(size)
+
+        # go by all the controls and call Layout
+
+        for items in self._items:
+            items.ResizeItem((vertical and [size.GetWidth()] or \
+                              [size.GetHeight()])[0], vertical)
+
+        self.Thaw()            
+##        self.Refresh()
+        
+
+    def OnPaint(self, event):
+        """ Handles the EVT_PAINT event in the FoldPanelItem. """
+  
+        # draw all the items that are lines
+
+        dc = wx.PaintDC(self)
+        vertical = self.IsVertical()
+
+        for item in self._items:
+            
+            if item.GetType() == "SEPARATOR":
+                pen = wx.Pen(item.GetLineColour(), 1, wx.SOLID)
+                dc.SetPen(pen)
+                a = item.GetLeftSpacing()
+                b = item.GetLineY() + item.GetSpacing()
+                c = item.GetLineLength()
+                d = a + c
+                
+                if vertical:
+                    dc.DrawLine(a, b, d, b)
+                else:
+                    dc.DrawLine(b, a, b, d)
+        
+        event.Skip()
+        
+
+    def IsVertical(self):
+        """
+        Returns wether the CaptionBar Has Default Orientation Or Not.
+
+        Default is vertical.
+        """
+        
+        # grandparent of FoldPanelItem is FoldPanelBar
+        # default is vertical
+        
+        if isinstance(self.GetGrandParent(), FoldPanelBar):
+            return self.GetGrandParent().IsVertical()
+        else:
+            raise "ERROR: Wrong Parent " + repr(self.GetGrandParent())
+
+
+    def IsExpanded(self):
+        """ Returns expanded or collapsed status.
+
+        If the panel is expanded, True is returned. """
+        
+        return not self._captionBar.IsCollapsed()
+
+    
+    def GetItemPos(self):
+        """ Returns item's position. """
+        
+        return self._itemPos
+
+
+    def Collapse(self):
+        # this should not be called by the user, because it doesn't trigger the
+        # parent  to tell it that we are collapsed or expanded, it only changes
+        # visual state
+        
+        self._captionBar.Collapse()
+        self.ResizePanel()
+
+
+    def Expand(self):
+        # this should not be called by the user, because it doesn't trigger the
+        # parent to tell it that we are collapsed or expanded, it only changes
+        # visual state
+        
+        self._captionBar.Expand()
+        self.ResizePanel()
+
+
+    def GetPanelLength(self):
+        """ Returns size of panel. """
+        
+        if self._captionBar.IsCollapsed():
+            return self.GetCaptionLength()
+        elif self._userSized:
+            return self._UserSize
+        
+        return self._PanelSize
+
+
+    def GetCaptionLength(self):
+        """ Returns height of caption only. This is for folding calculation purposes. """
+        
+        size = self._captionBar.GetSize()
+        return (self.IsVertical() and [size.GetHeight()] or [size.GetWidth()])[0]
+
+
+    def ApplyCaptionStyle(self, cbstyle):
+        """ Applies the style defined in cbstyle to the CaptionBar."""
+        
+        self._captionBar.SetCaptionStyle(cbstyle)
+
+
+    def GetCaptionStyle(self):
+        """
+        Returns the current style of the captionbar in a CaptionBarStyle class.
+
+        This can be used to change and set back the changes.
+        """
+        
+        return self._captionBar.GetCaptionStyle()
+
+
+# ----------------------------------------------------------------------------------- #
+# class FoldWindowItem
+#    This class is a child sibling of the FoldPanelItem class. It will contain
+#    wxWindow that can be either a separator (a colored line simulated by a wxWindow)
+#    or a wxPython controls (such as a wxButton, a wxListCtrl etc...).
+# ----------------------------------------------------------------------------------- #
+
+class FoldWindowItem:
+
+    def __init__(self, parent, window=None, **kw):
+        """
+        Default Class Constructor
+        
+        Initialize with:
+
+            Type = "WINDOW", flags = FPB_ALIGN_WIDTH,
+            Spacing = FPB_DEFAULT_SPACING,
+            leftSpacing = FPB_DEFAULT_LEFTSPACING,
+            rightSpacing = FPB_DEFAULT_RIGHTSPACING
+
+            or:
+
+            Type = "SEPARATOR"
+            y, lineColor = wx.BLACK,
+            flags = FPB_ALIGN_WIDTH,
+            Spacing = FPB_DEFAULT_SPACING,
+            leftSpacing = FPB_DEFAULT_LEFTLINESPACING,
+            rightSpacing = FPB_DEFAULT_RIGHTLINESPACING
+        """
+
+
+        if not kw.has_key("Type"):
+            raise 'ERROR: Missing Window Type Information. This Should Be "WINDOW" Or "SEPARATOR"'
+
+        if kw.get("Type") == "WINDOW":
+            # Window constructor. This initialises the class as a wx.Window Type
+            
+            if kw.has_key("flags"):
+                self._flags = kw.get("flags")
+            else:
+                self._flags = FPB_ALIGN_WIDTH
+            if kw.has_key("Spacing"):
+                self._Spacing = kw.get("Spacing")
+            else:
+                self._Spacing = FPB_DEFAULT_SPACING
+            if kw.has_key("leftSpacing"):
+                self._leftSpacing = kw.get("leftSpacing")
+            else:
+                self._leftSpacing = FPB_DEFAULT_LEFTSPACING
+            if kw.has_key("rightSpacing"):
+                self._rightSpacing = kw.get("rightSpacing")
+            else:
+                self._rightSpacing = FPB_DEFAULT_RIGHTSPACING
+
+            self._lineY = 0
+            self._sepLineColour = None
+            self._wnd = window
+            
+
+        elif kw.get("Type") == "SEPARATOR":
+            # separator constructor. This initialises the class as a separator type
+            
+            if kw.has_key("y"):
+                self._lineY = kw.get("y")
+            else:
+                raise "ERROR: Undefined Y Position For The Separator"
+            if kw.has_key("lineColour"):
+                self._sepLineColour = kw.get("lineColour")
+            else:
+                self._sepLineColour = wx.BLACK
+            if kw.has_key("flags"):
+                self._flags = kw.get("flags")
+            else:
+                self._flags = FPB_ALIGN_WIDTH
+            if kw.has_key("Spacing"):
+                self._Spacing = kw.get("Spacing")
+            else:
+                self._Spacing = FPB_DEFAULT_SPACING
+            if kw.has_key("leftSpacing"):
+                self._leftSpacing = kw.get("leftSpacing")
+            else:
+                self._leftSpacing = FPB_DEFAULT_LEFTSPACING
+            if kw.has_key("rightSpacing"):
+                self._rightSpacing = kw.get("rightSpacing")
+            else:
+                self._rightSpacing = FPB_DEFAULT_RIGHTSPACING
+
+            self._wnd = window
+
+        else:
+            raise "ERROR: Undefined Window Type Selected: " + repr(kw.get("Type"))
+
+        self._type = kw.get("Type")
+        self._lineLength = 0
+        
+
+    def GetType(self):
+        return self._type
+
+    def GetLineY(self):
+        return self._lineY
+
+    def GetLineLength(self):
+        return self._lineLength
+
+    def GetLineColour(self):
+        return self._sepLineColour
+
+    def GetLeftSpacing(self):
+        return self._leftSpacing
+
+    def GetRightSpacing(self):
+        return self._rightSpacing
+
+    def GetSpacing(self):
+        return self._Spacing
+
+
+    def GetWindowLength(self, vertical=True):
+        """ Returns space needed by the window if type is FoldWindowItem "WINDOW"
+        and returns the total size plus the extra spacing."""
+
+        value = 0
+        if self._type == "WINDOW":
+            size = self._wnd.GetSize()
+            value = (vertical and [size.GetHeight()] or [size.GetWidth()])[0] + \
+                    self._Spacing
+            
+        elif self._type == "SEPARATOR":
+            value = 1 + self._Spacing
+
+        return value
+
+
+    def ResizeItem(self, size, vertical=True):
+        """
+        Resizes the element, whatever it is.
+        
+        A separator or line will be always aligned by width or height
+        depending on orientation of the whole panel.
+        """
+        
+        if self._flags & FPB_ALIGN_WIDTH:
+            # align by taking full width
+            mySize = size - self._leftSpacing - self._rightSpacing
+
+            if mySize < 0:
+                mySize = 10  # can't have negative width
+
+            if self._type == "SEPARATOR":
+                self._lineLength = mySize
+            else:
+                xsize = (vertical and [mySize] or [-1])[0]
+                ysize = (vertical and [-1] or [mySize])[0]
+
+                self._wnd.SetSize((xsize, ysize))
+