From: Robin Dunn Date: Wed, 30 Mar 2005 22:58:23 +0000 (+0000) Subject: Added wx.lib.foldpanelbar, Andrea Gavana's port of Jorgen Bodde's C++ X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/42f5333f806d9c3609a32455d7cf7ec633bce8cc Added wx.lib.foldpanelbar, Andrea Gavana's port of Jorgen Bodde's C++ wxFoldPanelBar classes to Python. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33207 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/wxPython/demo/FoldPanelBar.py b/wxPython/demo/FoldPanelBar.py new file mode 100644 index 0000000000..9664b06084 --- /dev/null +++ b/wxPython/demo/FoldPanelBar.py @@ -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>\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:]) + diff --git a/wxPython/demo/Main.py b/wxPython/demo/Main.py index 4938824bf8..7fbad495e4 100644 --- a/wxPython/demo/Main.py +++ b/wxPython/demo/Main.py @@ -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', diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index b0305246c2..2de2a1d91d 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -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 index 0000000000..abbce9a846 --- /dev/null +++ b/wxPython/wx/lib/foldpanelbar.py @@ -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)) +