X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/wx/lib/buttonpanel.py?ds=inline diff --git a/wxPython/wx/lib/buttonpanel.py b/wxPython/wx/lib/buttonpanel.py deleted file mode 100644 index d47b9c9482..0000000000 --- a/wxPython/wx/lib/buttonpanel.py +++ /dev/null @@ -1,1992 +0,0 @@ -# --------------------------------------------------------------------------- # -# FANCYBUTTONPANEL Widget wxPython IMPLEMENTATION -# -# Original C++ Code From Eran. You Can Find It At: -# -# http://wxforum.shadonet.com/viewtopic.php?t=6619 -# -# License: wxWidgets license -# -# -# Python Code By: -# -# Andrea Gavana, @ 02 Oct 2006 -# Latest Revision: 17 Oct 2006, 17.00 GMT -# -# -# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please -# Write To Me At: -# -# andrea.gavana@gmail.com -# gavana@kpo.kz -# -# Or, Obviously, To The wxPython Mailing List!!! -# -# -# End Of Comments -# --------------------------------------------------------------------------- # - -""" -With `ButtonPanel` class you have a panel with gradient coloring -on it and with the possibility to place some buttons on it. Using a -standard panel with normal wx.Buttons leads to an ugly result: the -buttons are placed correctly on the panel - but with grey area around -them. Gradient coloring is kept behind the images - this was achieved -due to the PNG format and the transparency of the bitmaps. - -The image are functioning like a buttons and can be caught in your -code using the usual self.Bind(wx.EVT_BUTTON, self.OnButton) method. - -The control is generic, and support theming (well, I tested it under -Windows with the three defauls themes: grey, blue, silver and the -classic look). - - -Usage ------ - -ButtonPanel supports 4 alignments: left, right, top, bottom, which have a -different meaning and behavior wrt wx.Toolbar. The easiest thing is to try -the demo to understand, but I'll try to explain how it works. - -CASE 1: ButtonPanel has a main caption text - -Left alignment means ButtonPanel is horizontal, with the text aligned to the -left. When you shrink the demo frame, if there is not enough room for all -the controls to be shown, the controls closest to the text are hidden; - -Right alignment means ButtonPanel is horizontal, with the text aligned to the -right. Item layout as above; - -Top alignment means ButtonPanel is vertical, with the text aligned to the top. -Item layout as above; - -Bottom alignment means ButtonPanel is vertical, with the text aligned to the -bottom. Item layout as above. - - -CASE 2: ButtonPanel has *no* main caption text -In this case, left and right alignment are the same (as top and bottom are the same), -but the layout strategy changes: now if there is not enough room for all the controls -to be shown, the last added items are hidden ("last" means on the far right for -horizontal ButtonPanels and far bottom for vertical ButtonPanels). - - -The following example shows a simple implementation that uses ButtonPanel -inside a very simple frame:: - - class MyFrame(wx.Frame): - - def __init__(self, parent, id=-1, title="ButtonPanel", pos=wx.DefaultPosition, - size=(800, 600), style=wx.DEFAULT_FRAME_STYLE): - - wx.Frame.__init__(self, parent, id, title, pos, size, style) - - mainPanel = wx.Panel(self, -1) - self.logtext = wx.TextCtrl(mainPanel, -1, "", style=wx.TE_MULTILINE) - - vSizer = wx.BoxSizer(wx.VERTICAL) - mainPanel.SetSizer(vSizer) - - alignment = BP_ALIGN_RIGHT - - titleBar = ButtonPanel(mainPanel, -1, "A Simple Test & Demo") - - btn1 = ButtonInfo(wx.NewId(), wx.Bitmap("png4.png", wx.BITMAP_TYPE_PNG)) - titleBar.AddButton(btn1) - self.Bind(wx.EVT_BUTTON, self.OnButton, btn1) - - btn2 = ButtonInfo(wx.NewId(), wx.Bitmap("png3.png", wx.BITMAP_TYPE_PNG)) - titleBar.AddButton(btn2) - self.Bind(wx.EVT_BUTTON, self.OnButton, btn2) - - btn3 = ButtonInfo(wx.NewId(), wx.Bitmap("png2.png", wx.BITMAP_TYPE_PNG)) - titleBar.AddButton(btn3) - self.Bind(wx.EVT_BUTTON, self.OnButton, btn3) - - btn4 = ButtonInfo(wx.NewId(), wx.Bitmap("png1.png", wx.BITMAP_TYPE_PNG)) - titleBar.AddButton(btn4) - self.Bind(wx.EVT_BUTTON, self.OnButton, btn4) - - vSizer.Add(titleBar, 0, wx.EXPAND) - vSizer.Add((20, 20)) - vSizer.Add(self.logtext, 1, wx.EXPAND|wx.ALL, 5) - - vSizer.Layout() - - # our normal wxApp-derived class, as usual - - app = wx.PySimpleApp() - - frame = MyFrame(None) - app.SetTopWindow(frame) - frame.Show() - - app.MainLoop() - - -License And Version: - -ButtonPanel Is Freeware And Distributed Under The wxPython License. - -Latest Revision: Andrea Gavana @ 12 Oct 2006, 17.00 GMT -Version 0.3. - -""" - - -import wx - -# Some constants to tune the BPArt class -BP_BACKGROUND_COLOR = 0 -""" Background brush colour when no gradient shading exists. """ -BP_GRADIENT_COLOR_FROM = 1 -""" Starting gradient colour, used only when BP_USE_GRADIENT style is applied. """ -BP_GRADIENT_COLOR_TO = 2 -""" Ending gradient colour, used only when BP_USE_GRADIENT style is applied. """ -BP_BORDER_COLOR = 3 -""" Pen colour to paint the border of ButtonPanel. """ -BP_TEXT_COLOR = 4 -""" Main ButtonPanel caption colour. """ -BP_BUTTONTEXT_COLOR = 5 -""" Text colour for buttons with text. """ -BP_BUTTONTEXT_INACTIVE_COLOR = 6 -""" Text colour for inactive buttons with text. """ -BP_SELECTION_BRUSH_COLOR = 7 -""" Brush colour to be used when hovering or selecting a button. """ -BP_SELECTION_PEN_COLOR = 8 -""" Pen colour to be used when hovering or selecting a button. """ -BP_SEPARATOR_COLOR = 9 -""" Pen colour used to paint the separators. """ -BP_TEXT_FONT = 10 -""" Font of the ButtonPanel main caption. """ -BP_BUTTONTEXT_FONT = 11 -""" Text font for the buttons with text. """ - -BP_BUTTONTEXT_ALIGN_BOTTOM = 12 -""" Flag that indicates the image and text in buttons is stacked. """ -BP_BUTTONTEXT_ALIGN_RIGHT = 13 -""" Flag that indicates the text is shown alongside the image in buttons with text. """ - -BP_SEPARATOR_SIZE = 14 -""" -Separator size. NB: This is not the line width, but the sum of the space before -and after the separator line plus the width of the line. -""" -BP_MARGINS_SIZE = 15 -""" -Size of the left/right margins in ButtonPanel (top/bottom for vertically -aligned ButtonPanels). -""" -BP_BORDER_SIZE = 16 -""" Size of the border. """ -BP_PADDING_SIZE = 17 -""" Inter-tool separator size. """ - -# Caption Gradient Type -BP_GRADIENT_NONE = 0 -""" No gradient shading should be used to paint the background. """ -BP_GRADIENT_VERTICAL = 1 -""" Vertical gradient shading should be used to paint the background. """ -BP_GRADIENT_HORIZONTAL = 2 -""" Horizontal gradient shading should be used to paint the background. """ - -# Flags for HitTest() method -BP_HT_BUTTON = 200 -BP_HT_NONE = 201 - -# Alignment of buttons in the panel -BP_ALIGN_RIGHT = 1 -BP_ALIGN_LEFT = 2 -BP_ALIGN_TOP = 4 -BP_ALIGN_BOTTOM = 8 - -# ButtonPanel styles -BP_DEFAULT_STYLE = 1 -BP_USE_GRADIENT = 2 - -# Delay used to cancel the longHelp in the statusbar field -_DELAY = 3000 - - -# Check for the new method in 2.7 (not present in 2.6.3.3) -if wx.VERSION_STRING < "2.7": - wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point) - - -def BrightenColour(color, factor): - """ Bright the input colour by a factor.""" - - val = color.Red()*factor - if val > 255: - red = 255 - else: - red = val - - val = color.Green()*factor - if val > 255: - green = 255 - else: - green = val - - val = color.Blue()*factor - if val > 255: - blue = 255 - else: - blue = val - - return wx.Color(red, green, blue) - - -def GrayOut(anImage): - """ - Convert the given image (in place) to a grayed-out version, - appropriate for a 'Disabled' appearance. - """ - - factor = 0.7 # 0 < f < 1. Higher Is Grayer - - anImage = anImage.ConvertToImage() - if anImage.HasAlpha(): - anImage.ConvertAlphaToMask(1) - - if anImage.HasMask(): - maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue()) - else: - maskColor = None - - data = map(ord, list(anImage.GetData())) - - for i in range(0, len(data), 3): - - pixel = (data[i], data[i+1], data[i+2]) - pixel = MakeGray(pixel, factor, maskColor) - - for x in range(3): - data[i+x] = pixel[x] - - anImage.SetData(''.join(map(chr, data))) - - anImage = anImage.ConvertToBitmap() - - return anImage - - -def MakeGray((r,g,b), factor, maskColor): - """ - Make a pixel grayed-out. If the pixel matches the maskColor, it won't be - changed. - """ - - if (r,g,b) != maskColor: - return map(lambda x: int((230 - x) * factor) + x, (r,g,b)) - else: - return (r,g,b) - - -# ---------------------------------------------------------------------------- # -# Class BPArt -# Handles all the drawings for buttons, separators and text and allows the -# programmer to set colours, sizes and gradient shadings for ButtonPanel -# ---------------------------------------------------------------------------- # - -class BPArt: - """ - BPArt is an art provider class which does all of the drawing for ButtonPanel. - This allows the library caller to customize the BPArt or to completely replace - all drawing with custom BPArts. - """ - - def __init__(self, parentStyle): - """ Default class constructor. """ - - base_color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) - - self._background_brush = wx.Brush(base_color, wx.SOLID) - self._gradient_color_to = wx.WHITE - self._gradient_color_from = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION) - - if parentStyle & BP_USE_GRADIENT: - self._border_pen = wx.Pen(wx.WHITE, 3) - self._caption_text_color = wx.WHITE - self._buttontext_color = wx.Colour(70, 143, 255) - self._separator_pen = wx.Pen(BrightenColour(self._gradient_color_from, 1.4)) - self._gradient_type = BP_GRADIENT_VERTICAL - else: - self._border_pen = wx.Pen(BrightenColour(base_color, 0.9), 3) - self._caption_text_color = wx.BLACK - self._buttontext_color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT) - self._separator_pen = wx.Pen(BrightenColour(base_color, 0.9)) - self._gradient_type = BP_GRADIENT_NONE - - self._buttontext_inactive_color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT) - self._selection_brush = wx.Brush(wx.Color(225, 225, 255)) - self._selection_pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)) - - sysfont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) - self._caption_font = wx.Font(sysfont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.BOLD, - False, sysfont.GetFaceName()) - self._buttontext_font = wx.Font(sysfont.GetPointSize(), wx.DEFAULT, wx.NORMAL, wx.NORMAL, - False, sysfont.GetFaceName()) - - self._separator_size = 7 - self._margins_size = wx.Size(6, 6) - self._caption_border_size = 3 - self._padding_size = wx.Size(6, 6) - - - def GetMetric(self, id): - """ Returns sizes of customizable options. """ - - if id == BP_SEPARATOR_SIZE: - return self._separator_size - elif id == BP_MARGINS_SIZE: - return self._margins_size - elif id == BP_BORDER_SIZE: - return self._caption_border_size - elif id == BP_PADDING_SIZE: - return self._padding_size - else: - raise "\nERROR: Invalid Metric Ordinal. " - - - def SetMetric(self, id, new_val): - """ Sets sizes for customizable options. """ - - if id == BP_SEPARATOR_SIZE: - self._separator_size = new_val - elif id == BP_MARGINS_SIZE: - self._margins_size = new_val - elif id == BP_BORDER_SIZE: - self._caption_border_size = new_val - self._border_pen.SetWidth(new_val) - elif id == BP_PADDING_SIZE: - self._padding_size = new_val - else: - raise "\nERROR: Invalid Metric Ordinal. " - - - def GetColor(self, id): - """ Returns colours of customizable options. """ - - if id == BP_BACKGROUND_COLOR: - return self._background_brush.GetColour() - elif id == BP_GRADIENT_COLOR_FROM: - return self._gradient_color_from - elif id == BP_GRADIENT_COLOR_TO: - return self._gradient_color_to - elif id == BP_BORDER_COLOR: - return self._border_pen.GetColour() - elif id == BP_TEXT_COLOR: - return self._caption_text_color - elif id == BP_BUTTONTEXT_COLOR: - return self._buttontext_color - elif id == BP_BUTTONTEXT_INACTIVE_COLOR: - return self._buttontext_inactive_color - elif id == BP_SELECTION_BRUSH_COLOR: - return self._selection_brush.GetColour() - elif id == BP_SELECTION_PEN_COLOR: - return self._selection_pen.GetColour() - elif id == BP_SEPARATOR_COLOR: - return self._separator_pen.GetColour() - else: - raise "\nERROR: Invalid Colour Ordinal. " - - - def SetColor(self, id, colour): - """ Sets colours for customizable options. """ - - if id == BP_BACKGROUND_COLOR: - self._background_brush.SetColour(colour) - elif id == BP_GRADIENT_COLOR_FROM: - self._gradient_color_from = colour - elif id == BP_GRADIENT_COLOR_TO: - self._gradient_color_to = colour - elif id == BP_BORDER_COLOR: - self._border_pen.SetColour(colour) - elif id == BP_TEXT_COLOR: - self._caption_text_color = colour - elif id == BP_BUTTONTEXT_COLOR: - self._buttontext_color = colour - elif id == BP_BUTTONTEXT_INACTIVE_COLOR: - self._buttontext_inactive_color = colour - elif id == BP_SELECTION_BRUSH_COLOR: - self._selection_brush.SetColour(colour) - elif id == BP_SELECTION_PEN_COLOR: - self._selection_pen.SetColour(colour) - elif id == BP_SEPARATOR_COLOR: - self._separator_pen.SetColour(colour) - else: - raise "\nERROR: Invalid Colour Ordinal. " - - - GetColour = GetColor - SetColour = SetColor - - - def SetFont(self, id, font): - """ Sets font for customizable options. """ - - if id == BP_TEXT_FONT: - self._caption_font = font - elif id == BP_BUTTONTEXT_FONT: - self._buttontext_font = font - - - def GetFont(self, id): - """ Returns font of customizable options. """ - - if id == BP_TEXT_FONT: - return self._caption_font - elif id == BP_BUTTONTEXT_FONT: - return self._buttontext_font - - return wx.NoneFont - - - def SetGradientType(self, gradient): - """ Sets the gradient type for BPArt drawings. """ - - self._gradient_type = gradient - - - def GetGradientType(self): - """ Returns the gradient type for BPArt drawings. """ - - return self._gradient_type - - - def DrawSeparator(self, dc, rect, isVertical): - """ Draws a separator in ButtonPanel. """ - - dc.SetPen(self._separator_pen) - - if isVertical: - ystart = yend = rect.y + rect.height/2 - xstart = int(rect.x + 1.5*self._caption_border_size) - xend = int(rect.x + rect.width - 1.5*self._caption_border_size) - dc.DrawLine(xstart, ystart, xend, yend) - else: - xstart = xend = rect.x + rect.width/2 - ystart = int(rect.y + 1.5*self._caption_border_size) - yend = int(rect.y + rect.height - 1.5*self._caption_border_size) - dc.DrawLine(xstart, ystart, xend, yend) - - - def DrawCaption(self, dc, rect, captionText): - """ Draws the main caption text in ButtonPanel. """ - - textColour = self._caption_text_color - textFont = self._caption_font - padding = self._padding_size - - dc.SetTextForeground(textColour) - dc.SetFont(textFont) - - dc.DrawText(captionText, rect.x + padding.x, rect.y+padding.y) - - - def DrawButton(self, dc, rect, parentSize, buttonBitmap, isVertical, - buttonStatus, isToggled, textAlignment, text=""): - """ Draws a button in ButtonPanel, together with its text (if any). """ - - bmpxsize, bmpysize = buttonBitmap.GetWidth(), buttonBitmap.GetHeight() - dx = dy = focus = 0 - - borderw = self._caption_border_size - padding = self._padding_size - - buttonFont = self._buttontext_font - dc.SetFont(buttonFont) - - if isVertical: - - rect = wx.Rect(borderw, rect.y, rect.width-2*borderw, rect.height) - - if text != "": - - textW, textH = dc.GetTextExtent(text) - - if textAlignment == BP_BUTTONTEXT_ALIGN_RIGHT: - fullExtent = bmpxsize + padding.x/2 + textW - bmpypos = rect.y + (rect.height - bmpysize)/2 - bmpxpos = rect.x + (rect.width - fullExtent)/2 - textxpos = bmpxpos + padding.x/2 + bmpxsize - textypos = bmpypos + (bmpysize - textH)/2 - else: - bmpxpos = rect.x + (rect.width - bmpxsize)/2 - bmpypos = rect.y + padding.y - textxpos = rect.x + (rect.width - textW)/2 - textypos = bmpypos + bmpysize + padding.y/2 - else: - bmpxpos = rect.x + (rect.width - bmpxsize)/2 - bmpypos = rect.y + (rect.height - bmpysize)/2 - - - else: - - rect = wx.Rect(rect.x, borderw, rect.width, rect.height-2*borderw) - - if text != "": - - textW, textH = dc.GetTextExtent(text) - - if textAlignment == BP_BUTTONTEXT_ALIGN_RIGHT: - fullExtent = bmpxsize + padding.x/2 + textW - bmpypos = rect.y + (rect.height - bmpysize)/2 - bmpxpos = rect.x + (rect.width - fullExtent)/2 - textxpos = bmpxpos + padding.x/2 + bmpxsize - textypos = bmpypos + (bmpysize - textH)/2 - else: - fullExtent = bmpysize + padding.y/2 + textH - bmpxpos = rect.x + (rect.width - bmpxsize)/2 - bmpypos = rect.y + (rect.height - fullExtent)/2 - textxpos = rect.x + (rect.width - textW)/2 - textypos = bmpypos + bmpysize + padding.y/2 - else: - bmpxpos = rect.x + (rect.width - bmpxsize)/2 - bmpypos = rect.y + (rect.height - bmpysize)/2 - - # Draw a button - # [ Padding | Text | .. Buttons .. | Padding ] - - if buttonStatus in ["Pressed", "Toggled", "Hover"]: - dc.SetBrush(self._selection_brush) - dc.SetPen(self._selection_pen) - dc.DrawRoundedRectangleRect(rect, 4) - - if buttonStatus == "Pressed" or isToggled: - dx = dy = 1 - - dc.DrawBitmap(buttonBitmap, bmpxpos+dx, bmpypos+dy, True) - - if text != "": - isEnabled = buttonStatus != "Disabled" - self.DrawLabel(dc, text, isEnabled, textxpos+dx, textypos+dy) - - - def DrawLabel(self, dc, text, isEnabled, xpos, ypos): - """ Draws the label for a button. """ - - if not isEnabled: - dc.SetTextForeground(self._buttontext_inactive_color) - else: - dc.SetTextForeground(self._buttontext_color) - - dc.DrawText(text, xpos, ypos) - - - def DrawButtonPanel(self, dc, rect, style): - """ Paint the ButtonPanel's background. """ - - if style & BP_USE_GRADIENT: - # Draw gradient color in the backgroud of the panel - self.FillGradientColor(dc, rect) - - # Draw a rectangle around the panel - backBrush = (style & BP_USE_GRADIENT and [wx.TRANSPARENT_BRUSH] or \ - [self._background_brush])[0] - - dc.SetBrush(backBrush) - dc.SetPen(self._border_pen) - dc.DrawRectangleRect(rect) - - - def FillGradientColor(self, dc, rect): - """ Gradient fill from colour 1 to colour 2 with top to bottom or left to right. """ - - if rect.height < 1 or rect.width < 1: - return - - isVertical = self._gradient_type == BP_GRADIENT_VERTICAL - size = (isVertical and [rect.height] or [rect.width])[0] - start = (isVertical and [rect.y] or [rect.x])[0] - - # calculate gradient coefficients - - col2 = self._gradient_color_from - col1 = self._gradient_color_to - - rf, gf, bf = 0, 0, 0 - rstep = float((col2.Red() - col1.Red()))/float(size) - gstep = float((col2.Green() - col1.Green()))/float(size) - bstep = float((col2.Blue() - col1.Blue()))/float(size) - - for coord in xrange(start, start + size): - - currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf) - dc.SetBrush(wx.Brush(currCol, wx.SOLID)) - dc.SetPen(wx.Pen(currCol)) - if isVertical: - dc.DrawLine(rect.x, coord, rect.x + rect.width, coord) - else: - dc.DrawLine(coord, rect.y, coord, rect.y + rect.height) - - rf += rstep - gf += gstep - bf += bstep - - -class StatusBarTimer(wx.Timer): - """Timer used for deleting StatusBar long help after _DELAY seconds.""" - - def __init__(self, owner): - """ - Default class constructor. - For internal use: do not call it in your code! - """ - - wx.Timer.__init__(self) - self._owner = owner - - - def Notify(self): - """The timer has expired.""" - - self._owner.OnStatusBarTimer() - - -class Control(wx.EvtHandler): - - def __init__(self, parent, size=wx.Size(-1, -1)): - """ - Default class constructor. - - Base class for all pseudo controls - parent = parent object - size = (width, height) - """ - - wx.EvtHandler.__init__(self) - - self._parent = parent - self._id = wx.NewId() - self._size = size - self._isshown = True - self._focus = False - - - def Show(self, show=True): - """ Shows or hide the control. """ - - self._isshown = show - - - def Hide(self): - """ Hides the control. """ - - self.Show(False) - - - def IsShown(self): - """ Returns whether the control is shown or not. """ - - return self._isshown - - - def GetId(self): - """ Returns the control id. """ - - return self._id - - - def GetBestSize(self): - """ Returns the control best size. """ - - return self._size - - - def Disable(self): - """ Disables the control. """ - - self.Enable(False) - - - def Enable(self, value=True): - """ Enables or disables the control. """ - - self.disabled = not value - - - def SetFocus(self, focus=True): - """ Sets or kills the focus on the control. """ - - self._focus = focus - - - def HasFocus(self): - """ Returns whether the control has the focus or not. """ - - return self._focus - - - def OnMouseEvent(self, x, y, event): - pass - - def Draw(self, rect): - pass - - - -class Sizer(object): - """ - Sizer - - This is a mix-in class to add pseudo support to a wx sizer. Just create - a new class that derives from this class and the wx sizer and intercepts - any methods that add to the wx sizer. - """ - def __init__(self): - self.children = [] # list of child Pseudo Controls - - # Sizer doesn't use the x1,y1,x2,y2 so allow it to - # be called with or without the coordinates - def Draw(self, dc, x1=0, y1=0, x2=0, y2=0): - for item in self.children: - # use sizer coordinates rather than - # what is passed in - c = item.GetUserData() - c.Draw(dc, item.GetRect()) - - def GetBestSize(self): - # this should be handled by the wx.Sizer based class - return self.GetMinSize() - - -# Pseudo BoxSizer -class BoxSizer(Sizer, wx.BoxSizer): - def __init__(self, orient=wx.HORIZONTAL): - wx.BoxSizer.__init__(self, orient) - Sizer.__init__(self) - - #------------------------------------------- - # sizer overrides (only called from Python) - #------------------------------------------- - # no support for user data if it's a pseudocontrol - # since that is already used - def Add(self, item, proportion=0, flag=0, border=0, userData=None): - # check to see if it's a pseudo object or sizer - if isinstance(item, Sizer): - szitem = wx.BoxSizer.Add(self, item, proportion, flag, border, item) - self.children.append(szitem) - elif isinstance(item, Control): # Control should be what ever class your controls come from - sz = item.GetBestSize() - # add a spacer to track this object - szitem = wx.BoxSizer.Add(self, sz, proportion, flag, border, item) - self.children.append(szitem) - else: - wx.BoxSizer.Add(self, item, proportion, flag, border, userData) - - def Prepend(self, item, proportion=0, flag=0, border=0, userData=None): - # check to see if it's a pseudo object or sizer - if isinstance(item, Sizer): - szitem = wx.BoxSizer.Prepend(self, item, proportion, flag, border, item) - self.children.append(szitem) - elif isinstance(item, Control): # Control should be what ever class your controls come from - sz = item.GetBestSize() - # add a spacer to track this object - szitem = wx.BoxSizer.Prepend(self, sz, proportion, flag, border, item) - self.children.insert(0,szitem) - else: - wx.BoxSizer.Prepend(self, item, proportion, flag, border, userData) - - def Insert(self, before, item, proportion=0, flag=0, border=0, userData=None, realIndex=None): - # check to see if it's a pseudo object or sizer - if isinstance(item, Sizer): - szitem = wx.BoxSizer.Insert(self, before, item, proportion, flag, border, item) - self.children.append(szitem) - elif isinstance(item, Control): # Control should be what ever class your controls come from - sz = item.GetBestSize() - # add a spacer to track this object - szitem = wx.BoxSizer.Insert(self, before, sz, proportion, flag, border, item) - if realIndex is not None: - self.children.insert(realIndex,szitem) - else: - self.children.insert(before,szitem) - - else: - wx.BoxSizer.Insert(self, before, item, proportion, flag, border, userData) - - - def Remove(self, indx, pop=-1): - - if pop >= 0: - self.children.pop(pop) - - wx.BoxSizer.Remove(self, indx) - - - def Layout(self): - - for ii, child in enumerate(self.GetChildren()): - item = child.GetUserData() - if item and child.IsShown(): - self.SetItemMinSize(ii, *item.GetBestSize()) - - wx.BoxSizer.Layout(self) - - - def Show(self, item, show=True): - - child = self.GetChildren()[item] - if child and child.GetUserData(): - child.GetUserData().Show(show) - - wx.BoxSizer.Show(self, item, show) - - -# ---------------------------------------------------------------------------- # -# Class Separator -# This class holds all the information to size and draw a separator inside -# ButtonPanel -# ---------------------------------------------------------------------------- # - -class Separator(Control): - - def __init__(self, parent): - """ Default class constructor. """ - - self._isshown = True - self._parent = parent - Control.__init__(self, parent) - - - def GetBestSize(self): - """ Returns the separator best size. """ - - # 10 is completely arbitrary, but it works anyhow - if self._parent.IsVertical(): - return wx.Size(10, self._parent._art.GetMetric(BP_SEPARATOR_SIZE)) - else: - return wx.Size(self._parent._art.GetMetric(BP_SEPARATOR_SIZE), 10) - - - def Draw(self, dc, rect): - """ Draws the separator. Actually the drawing is done in BPArt. """ - - if not self.IsShown(): - return - - isVertical = self._parent.IsVertical() - self._parent._art.DrawSeparator(dc, rect, isVertical) - - -# ---------------------------------------------------------------------------- # -# Class ButtonPanelText -# This class is used to hold data about the main caption in ButtonPanel -# ---------------------------------------------------------------------------- # - -class ButtonPanelText(Control): - - def __init__(self, parent, text=""): - """ Default class constructor. """ - - self._text = text - self._isshown = True - self._parent = parent - - Control.__init__(self, parent) - - - def GetText(self): - """ Returns the caption text. """ - - return self._text - - - def SetText(self, text=""): - """ Sets the caption text. """ - - self._text = text - - - def CreateDC(self): - """ Convenience function to create a DC. """ - - dc = wx.ClientDC(self._parent) - textFont = self._parent._art.GetFont(BP_TEXT_FONT) - dc.SetFont(textFont) - - return dc - - - def GetBestSize(self): - """ Returns the best size for the main caption in ButtonPanel. """ - - if self._text == "": - return wx.Size(0, 0) - - dc = self.CreateDC() - rect = self._parent.GetClientRect() - - tw, th = dc.GetTextExtent(self._text) - padding = self._parent._art.GetMetric(BP_PADDING_SIZE) - self._size = wx.Size(tw+2*padding.x, th+2*padding.y) - - return self._size - - - def Draw(self, dc, rect): - """ Draws the main caption. Actually the drawing is done in BPArt. """ - - if not self.IsShown(): - return - - captionText = self.GetText() - self._parent._art.DrawCaption(dc, rect, captionText) - - -# -- ButtonInfo class implementation ---------------------------------------- -# This class holds information about every button that is added to -# ButtonPanel. It is an auxiliary class that you should use -# every time you add a button. - -class ButtonInfo(Control): - - def __init__(self, parent, id=wx.ID_ANY, bmp=wx.NullBitmap, - status="Normal", text="", kind=wx.ITEM_NORMAL, - shortHelp="", longHelp=""): - """ - Default class constructor. - - Parameters: - - parent: the parent window (ButtonPanel); - - id: the button id; - - bmp: the associated bitmap; - - status: button status (pressed, hovered, normal). - - text: text to be displayed either below of to the right of the button - - kind: button kind, may be wx.ITEM_NORMAL for standard buttons or - wx.ITEM_CHECK for toggle buttons; - - shortHelp: a short help to be shown in the button tooltip; - - longHelp: this string is shown in the statusbar (if any) of the parent - frame when the mouse pointer is inside the button. - """ - - if id == wx.ID_ANY: - id = wx.NewId() - - self._status = status - self._rect = wx.Rect() - self._text = text - self._kind = kind - self._toggle = False - self._textAlignment = BP_BUTTONTEXT_ALIGN_BOTTOM - self._shortHelp = shortHelp - self._longHelp = longHelp - - if bmp: - disabledbmp = GrayOut(bmp) - else: - disabledbmp = wx.NullBitmap - - self._bitmaps = {"Normal": bmp, "Toggled": None, "Disabled": disabledbmp, - "Hover": None, "Pressed": None} - - Control.__init__(self, parent) - - - def GetBestSize(self): - """ Returns the best size for the button. """ - - xsize = self.GetBitmap().GetWidth() - ysize = self.GetBitmap().GetHeight() - - if self.HasText(): - # We have text in the button - dc = wx.ClientDC(self._parent) - normalFont = self._parent._art.GetFont(BP_BUTTONTEXT_FONT) - dc.SetFont(normalFont) - tw, th = dc.GetTextExtent(self.GetText()) - - if self.GetTextAlignment() == BP_BUTTONTEXT_ALIGN_BOTTOM: - xsize = max(xsize, tw) - ysize = ysize + th - else: - xsize = xsize + tw - ysize = max(ysize, th) - - border = self._parent._art.GetMetric(BP_BORDER_SIZE) - padding = self._parent._art.GetMetric(BP_PADDING_SIZE) - - if self._parent.IsVertical(): - xsize = xsize + 2*border - else: - ysize = ysize + 2*border - - self._size = wx.Size(xsize+2*padding.x, ysize+2*padding.y) - - return self._size - - - def Draw(self, dc, rect): - """ Draws the button on ButtonPanel. Actually the drawing is done in BPArt. """ - - if not self.IsShown(): - return - - buttonBitmap = self.GetBitmap() - isVertical = self._parent.IsVertical() - text = self.GetText() - parentSize = self._parent.GetSize()[not isVertical] - buttonStatus = self.GetStatus() - isToggled = self.GetToggled() - textAlignment = self.GetTextAlignment() - - self._parent._art.DrawButton(dc, rect, parentSize, buttonBitmap, isVertical, - buttonStatus, isToggled, textAlignment, text) - - self.SetRect(rect) - - - def CheckRefresh(self, status): - """ Checks whether a ButtonPanel repaint is needed or not. Convenience function. """ - - if status == self._status: - self._parent.RefreshRect(self.GetRect()) - - - def SetBitmap(self, bmp, status="Normal"): - """ Sets the associated bitmap. """ - - self._bitmaps[status] = bmp - self.CheckRefresh(status) - - - def GetBitmap(self, status=None): - """ Returns the associated bitmap. """ - - if status is None: - status = self._status - - if not self.IsEnabled(): - status = "Disabled" - - if self._bitmaps[status] is None: - return self._bitmaps["Normal"] - - return self._bitmaps[status] - - - def GetRect(self): - """ Returns the button rect. """ - - return self._rect - - - def GetStatus(self): - """ Returns the button status. """ - - return self._status - - - def GetId(self): - """ Returns the button id. """ - - return self._id - - - def SetRect(self, rect): - """ Sets the button rect. """ - - self._rect = rect - - - def SetStatus(self, status): - """ Sets the button status. """ - - if status == self._status: - return - - if self.GetToggled() and status == "Normal": - status = "Toggled" - - self._status = status - self._parent.RefreshRect(self.GetRect()) - - - def GetTextAlignment(self): - """ Returns the text alignment in the button (bottom or right). """ - - return self._textAlignment - - - def SetTextAlignment(self, alignment): - """ Sets the text alignment in the button (bottom or right). """ - - if alignment == self._textAlignment: - return - - self._textAlignment = alignment - - - def GetToggled(self): - """ Returns whether a wx.ITEM_CHECK button is toggled or not. """ - - if self._kind == wx.ITEM_NORMAL: - return False - - return self._toggle - - - def SetToggled(self, toggle=True): - """ Sets a wx.ITEM_CHECK button toggled/not toggled. """ - - if self._kind == wx.ITEM_NORMAL: - return - - self._toggle = toggle - - - def SetId(self, id): - """ Sets the button id. """ - - self._id = id - - - def AddStatus(self, name="Custom", bmp=wx.NullBitmap): - """ - Add a programmer-defined status in addition to the 5 default status: - - Normal; - - Disabled; - - Hover; - - Pressed; - - Toggled. - """ - - self._bitmaps.update({name: bmp}) - - - def Enable(self, enable=True): - - if enable: - self._status = "Normal" - else: - self._status = "Disabled" - - - def IsEnabled(self): - - return self._status != "Disabled" - - - def SetText(self, text=""): - """ Sets the text of the button. """ - - self._text = text - - - def GetText(self): - """ Returns the text associated to the button. """ - - return self._text - - - def HasText(self): - """ Returns whether the button has text or not. """ - - return self._text != "" - - - def SetKind(self, kind=wx.ITEM_NORMAL): - """ Sets the button type (standard or toggle). """ - - self._kind = kind - - - def GetKind(self): - """ Returns the button type (standard or toggle). """ - - return self._kind - - - def SetShortHelp(self, help=""): - """ Sets the help string to be shown in a tootip. """ - - self._shortHelp = help - - - def GetShortHelp(self): - """ Returns the help string shown in a tootip. """ - - return self._shortHelp - - - def SetLongHelp(self, help=""): - """ Sets the help string to be shown in the statusbar. """ - - self._longHelp = help - - - def GetLongHelp(self): - """ Returns the help string shown in the statusbar. """ - - return self._longHelp - - - Bitmap = property(GetBitmap, SetBitmap) - Id = property(GetId, SetId) - Rect = property(GetRect, SetRect) - Status = property(GetStatus, SetStatus) - - -# -- ButtonPanel class implementation ---------------------------------- -# This is the main class. - -class ButtonPanel(wx.PyPanel): - - def __init__(self, parent, id=wx.ID_ANY, text="", style=BP_DEFAULT_STYLE, - alignment=BP_ALIGN_LEFT, name="buttonPanel"): - """ - Default class constructor. - - - parent: parent window - - id: window ID - - text: text to draw - - style: window style - - alignment: alignment of buttons (left or right) - - name: window class name - """ - - wx.PyPanel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, - wx.NO_BORDER, name=name) - - self._vButtons = [] - self._vSeparators = [] - - self._nStyle = style - self._alignment = alignment - self._statusTimer = None - self._useHelp = True - self._freezeCount = 0 - self._currentButton = -1 - self._haveTip = False - - self._art = BPArt(style) - - self._controlCreated = False - - direction = (self.IsVertical() and [wx.VERTICAL] or [wx.HORIZONTAL])[0] - self._mainsizer = BoxSizer(direction) - self.SetSizer(self._mainsizer) - - margins = self._art.GetMetric(BP_MARGINS_SIZE) - - # First spacer to create some room before the first text/button/control - self._mainsizer.Add((margins.x, margins.y), 0) - - # Last spacer to create some room before the last text/button/control - self._mainsizer.Add((margins.x, margins.y), 0) - - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_MOTION, self.OnMouseMove) - self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) - self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) - self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) - self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow) - - self.SetBarText(text) - self.LayoutItems() - - - def SetBarText(self, text): - """ Sets the main caption text (leave text="" for no text). """ - - self.Freeze() - - text = text.strip() - - if self._controlCreated: - self.RemoveText() - - self._text = ButtonPanelText(self, text) - lenChildren = len(self._mainsizer.GetChildren()) - - if text == "": - # Even if we have no text, we insert it an empty spacer anyway - # it is easier to handle if you have to recreate the sizer after. - if self.IsStandard(): - self._mainsizer.Insert(1, self._text, 0, wx.ALIGN_CENTER, - userData=self._text, realIndex=0) - else: - self._mainsizer.Insert(lenChildren-1, self._text, 0, wx.ALIGN_CENTER, - userData=self._text, realIndex=lenChildren) - - return - - # We have text, so insert the text and an expandable spacer - # alongside it. "Standard" ButtonPanel are left or top aligned. - if self.IsStandard(): - self._mainsizer.Insert(1, self._text, 0, wx.ALIGN_CENTER, - userData=self._text, realIndex=0) - self._mainsizer.Insert(2, (0, 0), 1, wx.EXPAND) - - else: - self._mainsizer.Insert(lenChildren-1, self._text, 0, wx.ALIGN_CENTER, - userData=self._text, realIndex=lenChildren) - self._mainsizer.Insert(lenChildren-1, (0, 0), 1, wx.EXPAND) - - - def RemoveText(self): - """ Removes the main caption text. """ - - lenChildren = len(self._mainsizer.GetChildren()) - lenCustom = len(self._vButtons) + len(self._vSeparators) + 1 - - if self.IsStandard(): - # Detach the text - self._mainsizer.Remove(1, 0) - if self.HasBarText(): - # Detach the expandable spacer - self._mainsizer.Remove(1, -1) - else: - # Detach the text - self._mainsizer.Remove(lenChildren-2, lenCustom-1) - if self.HasBarText(): - # Detach the expandable spacer - self._mainsizer.Remove(lenChildren-3, -1) - - - def GetBarText(self): - """ Returns the main caption text. """ - - return self._text.GetText() - - - def HasBarText(self): - """ Returns whether ButtonPanel has a main caption text or not. """ - - return hasattr(self, "_text") and self._text.GetText() != "" - - - def AddButton(self, btnInfo): - """ - Adds a button to ButtonPanel. Remember to pass a ButtonInfo instance to - this method. See the demo for details. - """ - - lenChildren = len(self._mainsizer.GetChildren()) - self._mainsizer.Insert(lenChildren-1, btnInfo, 0, wx.ALIGN_CENTER|wx.EXPAND, userData=btnInfo) - - self._vButtons.append(btnInfo) - - - def AddSpacer(self, size=(0, 0), proportion=1, flag=wx.EXPAND): - """ Adds a spacer (stretchable or fixed-size) to ButtonPanel. """ - - lenChildren = len(self._mainsizer.GetChildren()) - self._mainsizer.Insert(lenChildren-1, size, proportion, flag) - - - def AddControl(self, control, proportion=0, flag=wx.ALIGN_CENTER|wx.ALL, border=None): - """ Adds a wxPython control to ButtonPanel. """ - - lenChildren = len(self._mainsizer.GetChildren()) - - if border is None: - border = self._art.GetMetric(BP_PADDING_SIZE) - border = max(border.x, border.y) - - self._mainsizer.Insert(lenChildren-1, control, proportion, flag, border) - - - def AddSeparator(self): - """ Adds a separator line to ButtonPanel. """ - - lenChildren = len(self._mainsizer.GetChildren()) - separator = Separator(self) - - self._mainsizer.Insert(lenChildren-1, separator, 0, wx.EXPAND) - self._vSeparators.append(separator) - - - def RemoveAllButtons(self): - """ Remove all the buttons from ButtonPanel. """ - - self._vButtons = [] - - - def RemoveAllSeparators(self): - """ Remove all the separators from ButtonPanel. """ - - self._vSeparators = [] - - - def GetAlignment(self): - """ Returns the button alignment (left, right, top, bottom). """ - - return self._alignment - - - def SetAlignment(self, alignment): - """ Sets the button alignment (left, right, top, bottom). """ - - if alignment == self._alignment: - return - - self.Freeze() - - text = self.GetBarText() - - # Remove the text in any case - self.RemoveText() - - # Remove the first and last spacers - self._mainsizer.Remove(0, -1) - self._mainsizer.Remove(len(self._mainsizer.GetChildren())-1, -1) - - self._alignment = alignment - - # Recreate the sizer accordingly to the new alignment - self.ReCreateSizer(text) - - - def IsVertical(self): - """ Returns whether ButtonPanel is vertically aligned or not. """ - - return self._alignment not in [BP_ALIGN_RIGHT, BP_ALIGN_LEFT] - - - def IsStandard(self): - """ Returns whether ButtonPanel is aligned "Standard" (left/top) or not. """ - - return self._alignment in [BP_ALIGN_LEFT, BP_ALIGN_TOP] - - - def DoLayout(self): - """ - Do the Layout for ButtonPanel. - NB: Call this method every time you make a modification to the layout - or to the customizable sizes of the pseudo controls. - """ - - margins = self._art.GetMetric(BP_MARGINS_SIZE) - lenChildren = len(self._mainsizer.GetChildren()) - - self._mainsizer.SetItemMinSize(0, (margins.x, margins.y)) - self._mainsizer.SetItemMinSize(lenChildren-1, (margins.x, margins.y)) - - self._controlCreated = True - self.LayoutItems() - - # *VERY* WEIRD: the sizer seems not to respond to any layout until I - # change the ButtonPanel size and restore it back - size = self.GetSize() - self.SetSize((size.x+1, size.y+1)) - self.SetSize((size.x, size.y)) - - if self.IsFrozen(): - self.Thaw() - - - def ReCreateSizer(self, text): - """ Recreates the ButtonPanel sizer accordingly to the alignment specified. """ - - children = self._mainsizer.GetChildren() - self.RemoveAllButtons() - self.RemoveAllSeparators() - - # Create a new sizer depending on the alignment chosen - direction = (self.IsVertical() and [wx.VERTICAL] or [wx.HORIZONTAL])[0] - self._mainsizer = BoxSizer(direction) - - margins = self._art.GetMetric(BP_MARGINS_SIZE) - # First spacer to create some room before the first text/button/control - self._mainsizer.Add((margins.x, margins.y), 0) - - # Last spacer to create some room before the last text/button/control - self._mainsizer.Add((margins.x, margins.y), 0) - - # This is needed otherwise SetBarText goes mad - self._controlCreated = False - - for child in children: - userData = child.GetUserData() - if userData: - if isinstance(userData, ButtonInfo): - # It is a ButtonInfo, can't be anything else - self.AddButton(child.GetUserData()) - elif isinstance(userData, Separator): - self.AddSeparator() - - else: - if child.IsSpacer(): - # This is a spacer, expandable or not - self.AddSpacer(child.GetSize(), child.GetProportion(), - child.GetFlag()) - else: - # This is a wxPython control - self.AddControl(child.GetWindow(), child.GetProportion(), - child.GetFlag(), child.GetBorder()) - - self.SetSizer(self._mainsizer) - - # Now add the text. It doesn't matter if there is no text - self.SetBarText(text) - - self.DoLayout() - - self.Thaw() - - - def DoGetBestSize(self): - """ Returns the best size of ButtonPanel. """ - - w = h = btnWidth = btnHeight = 0 - isVertical = self.IsVertical() - - padding = self._art.GetMetric(BP_PADDING_SIZE) - border = self._art.GetMetric(BP_BORDER_SIZE) - margins = self._art.GetMetric(BP_MARGINS_SIZE) - separator_size = self._art.GetMetric(BP_SEPARATOR_SIZE) - - # Add the space required for the main caption - if self.HasBarText(): - w, h = self._text.GetBestSize() - if isVertical: - h += padding.y - else: - w += padding.x - else: - w = h = border - - # Add the button's sizes - for btn in self._vButtons: - - bw, bh = btn.GetBestSize() - btnWidth = max(btnWidth, bw) - btnHeight = max(btnHeight, bh) - - if isVertical: - w = max(w, btnWidth) - h += bh - else: - h = max(h, btnHeight) - w += bw - - # Add the control's sizes - for control in self.GetControls(): - cw, ch = control.GetSize() - if isVertical: - h += ch - w = max(w, cw) - else: - w += cw - h = max(h, ch) - - # Add the separator's sizes and the 2 SizerItems at the beginning - # and at the end - if self.IsVertical(): - h += 2*margins.y + len(self._vSeparators)*separator_size - else: - w += 2*margins.x + len(self._vSeparators)*separator_size - - return wx.Size(w, h) - - - def OnPaint(self, event): - """ Handles the wx.EVT_PAINT event for ButtonPanel. """ - - dc = wx.BufferedPaintDC(self) - rect = self.GetClientRect() - - self._art.DrawButtonPanel(dc, rect, self._nStyle) - self._mainsizer.Draw(dc) - - - def OnEraseBackground(self, event): - """ Handles the wx.EVT_ERASE_BACKGROUND event for ButtonPanel (does nothing). """ - - pass - - - def OnSize(self, event): - """ Handles the wx.EVT_SIZE event for ButtonPanel. """ - - # NOTE: It seems like LayoutItems number of calls can be optimized in some way. - # Currently every DoLayout (or every parent Layout()) calls about 3 times - # the LayoutItems method. Any idea on how to improve it? - self.LayoutItems() - self.Refresh() - - event.Skip() - - - def LayoutItems(self): - """ - Layout the items using a different algorithm depending on the existance - of the main caption. - """ - - nonspacers, allchildren = self.GetNonFlexibleChildren() - - if self.HasBarText(): - self.FlexibleLayout(nonspacers, allchildren) - else: - self.SizeLayout(nonspacers, allchildren) - - self._mainsizer.Layout() - - - def SizeLayout(self, nonspacers, children): - """ Layout the items when no main caption exists. """ - - size = self.GetSize() - isVertical = self.IsVertical() - - corner = 0 - indx1 = len(nonspacers) - - for item in nonspacers: - corner += self.GetItemSize(item, isVertical) - if corner > size[isVertical]: - indx1 = nonspacers.index(item) - break - - # Leave out the last spacer, it has to be there always - for ii in xrange(len(nonspacers)-1): - indx = children.index(nonspacers[ii]) - self._mainsizer.Show(indx, ii < indx1) - - - def GetItemSize(self, item, isVertical): - """ Returns the size of an item in the main ButtonPanel sizer. """ - - if item.GetUserData(): - return item.GetUserData().GetBestSize()[isVertical] - else: - return item.GetSize()[isVertical] - - - def FlexibleLayout(self, nonspacers, allchildren): - """ Layout the items when the main caption exists. """ - - if len(nonspacers) < 2: - return - - isVertical = self.IsVertical() - isStandard = self.IsStandard() - - size = self.GetSize()[isVertical] - padding = self._art.GetMetric(BP_PADDING_SIZE) - - fixed = (isStandard and [nonspacers[1]] or [nonspacers[-2]])[0] - - if isStandard: - nonspacers.reverse() - leftendx = fixed.GetSize()[isVertical] + padding.x - else: - rightstartx = size - fixed.GetSize()[isVertical] - size = 0 - - count = lennonspacers = len(nonspacers) - - for item in nonspacers: - if isStandard: - size -= self.GetItemSize(item, isVertical) - if size < leftendx: - break - else: - size += self.GetItemSize(item, isVertical) - if size > rightstartx: - break - - count = count - 1 - - nonspacers.reverse() - - for jj in xrange(2, lennonspacers): - indx = allchildren.index(nonspacers[jj]) - self._mainsizer.Show(indx, jj >= count) - - - def GetNonFlexibleChildren(self): - """ - Returns all the ButtonPanel main sizer's children that are not - flexible spacers. - """ - - children1 = [] - children2 = self._mainsizer.GetChildren() - - for child in children2: - if child.IsSpacer(): - if child.GetUserData() or child.GetProportion() == 0: - children1.append(child) - else: - children1.append(child) - - return children1, children2 - - - def GetControls(self): - """ Returns the wxPython controls that belongs to ButtonPanel. """ - - children2 = self._mainsizer.GetChildren() - children1 = [child for child in children2 if not child.IsSpacer()] - - return children1 - - - def SetStyle(self, style): - """ Sets ButtonPanel style. """ - - if style == self._nStyle: - return - - self._nStyle = style - self.Refresh() - - - def GetStyle(self): - """ Returns the ButtonPanel style. """ - - return self._nStyle - - - def OnMouseMove(self, event): - """ Handles the wx.EVT_MOTION event for ButtonPanel. """ - - # Check to see if we are hovering a button - tabId, flags = self.HitTest(event.GetPosition()) - - if flags != BP_HT_BUTTON: - self.RemoveHelp() - self.RepaintOldSelection() - self._currentButton = -1 - return - - btn = self._vButtons[tabId] - - if not btn.IsEnabled(): - self.RemoveHelp() - self.RepaintOldSelection() - return - - if tabId != self._currentButton: - self.RepaintOldSelection() - - if btn.GetRect().Contains(event.GetPosition()): - if btn.GetStatus() != "Pressed": - btn.SetStatus("Hover") - else: - btn.SetStatus("Normal") - - if tabId != self._currentButton: - self.RemoveHelp() - self.DoGiveHelp(btn) - - self._currentButton = tabId - - event.Skip() - - - def OnLeftDown(self, event): - """ Handles the wx.EVT_LEFT_DOWN event for ButtonPanel. """ - - tabId, hit = self.HitTest(event.GetPosition()) - - if hit == BP_HT_BUTTON: - btn = self._vButtons[tabId] - if btn.IsEnabled(): - btn.SetStatus("Pressed") - self._currentButton = tabId - - - def OnLeftUp(self, event): - """ Handles the wx.EVT_LEFT_UP event for ButtonPanel. """ - - tabId, flags = self.HitTest(event.GetPosition()) - - if flags != BP_HT_BUTTON: - return - - hit = self._vButtons[tabId] - - if hit.GetStatus() == "Disabled": - return - - for btn in self._vButtons: - if btn != hit: - btn.SetFocus(False) - - if hit.GetStatus() == "Pressed": - hit.SetToggled(not hit.GetToggled()) - - # Update the button status to be hovered - hit.SetStatus("Hover") - hit.SetFocus() - self._currentButton = tabId - - # Fire a button click event - btnEvent = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, hit.GetId()) - self.GetEventHandler().ProcessEvent(btnEvent) - - - def OnMouseLeave(self, event): - """ Handles the wx.EVT_LEAVE_WINDOW event for ButtonPanel. """ - - # Reset all buttons statuses - for btn in self._vButtons: - if not btn.IsEnabled(): - continue - btn.SetStatus("Normal") - - self.RemoveHelp() - - event.Skip() - - - def OnMouseEnterWindow(self, event): - """ Handles the wx.EVT_ENTER_WINDOW event for ButtonPanel. """ - - tabId, flags = self.HitTest(event.GetPosition()) - - if flags == BP_HT_BUTTON: - - hit = self._vButtons[tabId] - - if hit.GetStatus() == "Disabled": - event.Skip() - return - - self.DoGiveHelp(hit) - self._currentButton = tabId - - event.Skip() - - - def DoGiveHelp(self, hit): - """ Gives tooltips and help in StatusBar. """ - - if not self.GetUseHelp(): - return - - shortHelp = hit.GetShortHelp() - if shortHelp: - self.SetToolTipString(shortHelp) - self._haveTip = True - - longHelp = hit.GetLongHelp() - if not longHelp: - return - - topLevel = wx.GetTopLevelParent(self) - - if isinstance(topLevel, wx.Frame) and topLevel.GetStatusBar(): - statusBar = topLevel.GetStatusBar() - - if self._statusTimer and self._statusTimer.IsRunning(): - self._statusTimer.Stop() - statusBar.PopStatusText(0) - - statusBar.PushStatusText(longHelp, 0) - self._statusTimer = StatusBarTimer(self) - self._statusTimer.Start(_DELAY, wx.TIMER_ONE_SHOT) - - - def RemoveHelp(self): - """ Removes the tooltips and statusbar help (if any) for a button. """ - - if not self.GetUseHelp(): - return - - if self._haveTip: - self.SetToolTipString("") - self._haveTip = False - - if self._statusTimer and self._statusTimer.IsRunning(): - topLevel = wx.GetTopLevelParent(self) - statusBar = topLevel.GetStatusBar() - self._statusTimer.Stop() - statusBar.PopStatusText(0) - self._statusTimer = None - - - def RepaintOldSelection(self): - """ Repaints the old selected/hovered button. """ - - current = self._currentButton - - if current == -1: - return - - btn = self._vButtons[current] - if not btn.IsEnabled(): - return - - btn.SetStatus("Normal") - - - def OnStatusBarTimer(self): - """ Handles the timer expiring to delete the longHelp in the StatusBar. """ - - topLevel = wx.GetTopLevelParent(self) - statusBar = topLevel.GetStatusBar() - statusBar.PopStatusText(0) - - - def SetUseHelp(self, useHelp=True): - """ Sets whether or not shortHelp and longHelp should be displayed. """ - - self._useHelp = useHelp - - - def GetUseHelp(self): - """ Returns whether or not shortHelp and longHelp should be displayed. """ - - return self._useHelp - - - def HitTest(self, pt): - """ - HitTest method for ButtonPanel. Returns the button (if any) and - a flag (if any). - """ - - for ii in xrange(len(self._vButtons)): - if not self._vButtons[ii].IsEnabled(): - continue - if self._vButtons[ii].GetRect().Contains(pt): - return ii, BP_HT_BUTTON - - return -1, BP_HT_NONE - - - def GetBPArt(self): - """ Returns the associated BPArt art provider. """ - - return self._art - - - def SetBPArt(self, art): - """ Sets a new BPArt to ButtonPanel. Useful only if another BPArt class is used. """ - - self._art = art - self.Refresh() - - if wx.VERSION < (2,7,1,1): - def Freeze(self): - """Freeze ButtonPanel.""" - - self._freezeCount = self._freezeCount + 1 - wx.PyPanel.Freeze(self) - - - def Thaw(self): - """Thaw ButtonPanel.""" - - if self._freezeCount == 0: - raise "\nERROR: Thawing Unfrozen ButtonPanel?" - - self._freezeCount = self._freezeCount - 1 - wx.PyPanel.Thaw(self) - - - def IsFrozen(self): - """ Returns whether a call to Freeze() has been done. """ - - return self._freezeCount != 0 - -