X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d14a1e28567de23c586bc80017073d0c39f8d18f..68fc5c8025e38b9d827383fbfe7ce509ae331c1f:/wxPython/wx/lib/buttons.py diff --git a/wxPython/wx/lib/buttons.py b/wxPython/wx/lib/buttons.py index eaba907b32..a7290cbbde 100644 --- a/wxPython/wx/lib/buttons.py +++ b/wxPython/wx/lib/buttons.py @@ -10,21 +10,17 @@ # Copyright: (c) 1999 by Total Control Software # Licence: wxWindows license #---------------------------------------------------------------------- +# 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net) +# +# o Updated for wx namespace +# o Tested with updated demo +# """ This module implements various forms of generic buttons, meaning that -they are not built on native controls but are self-drawn. - -The GenButton is the base. It acts like a normal button but you -are able to better control how it looks, bevel width, colours, etc. - -GenBitmapButton is a button with one or more bitmaps that show -the various states the button can be in. - -GenToggleButton stays depressed when clicked, until clicked again. - -GenBitmapToggleButton the same but with bitmaps. - +they are not built on native controls but are self-drawn. They act +like normal buttons but you are able to better control how they look, +bevel width, colours, etc. """ import wx @@ -34,8 +30,9 @@ import imageutils #---------------------------------------------------------------------- class GenButtonEvent(wx.PyCommandEvent): - def __init__(self, eventType, ID): - wx.PyCommandEvent.__init__(self, eventType, ID) + """Event sent from the generic buttons when the button is activated. """ + def __init__(self, eventType, id): + wx.PyCommandEvent.__init__(self, eventType, id) self.isDown = False self.theButton = None @@ -55,28 +52,32 @@ class GenButtonEvent(wx.PyCommandEvent): #---------------------------------------------------------------------- class GenButton(wx.PyControl): + """A generic button, and base class for the other generic buttons.""" + labelDelta = 1 - def __init__(self, parent, ID, label, + def __init__(self, parent, id=-1, label='', pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0, validator = wx.DefaultValidator, name = "genbutton"): - if style == 0: - style = wx.NO_BORDER - wx.PyControl.__init__(self, parent, ID, pos, size, style, validator, name) + cstyle = style + if cstyle == 0: + cstyle = wx.BORDER_NONE + wx.PyControl.__init__(self, parent, id, pos, size, cstyle, validator, name) self.up = True - self.bezelWidth = 2 self.hasFocus = False - self.useFocusInd = True + self.style = style + if style & wx.BORDER_NONE: + self.bezelWidth = 0 + self.useFocusInd = False + else: + self.bezelWidth = 2 + self.useFocusInd = True self.SetLabel(label) - self.SetPosition(pos) - font = parent.GetFont() - if not font.Ok(): - font = wx.SystemSettings.GetSystemFont(wx.SYS_DEFAULT_GUI_FONT) - self.SetFont(font) - self.SetBestSize(size) + self.InheritAttributes() + self.SetInitialSize(size) self.InitColours() self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) @@ -88,33 +89,25 @@ class GenButton(wx.PyControl): self.Bind(wx.EVT_KILL_FOCUS, self.OnLoseFocus) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) self.Bind(wx.EVT_PAINT, self.OnPaint) - def SetBestSize(self, size=None): + def SetInitialSize(self, size=None): """ Given the current font and bezel width settings, calculate and set a good size. """ if size is None: - size = wx.Size(-1,-1) - if type(size) == type(()): - size = wx.Size(size[0], size[1]) - size = wx.Size(size.width, size.height) # make a copy - - best = self.GetBestSize() - if size.width == -1: - size.width = best.width - if size.height == -1: - size.height = best.height - - self.SetSize(size) - + size = wx.DefaultSize + wx.PyControl.SetInitialSize(self, size) + SetBestSize = SetInitialSize + def DoGetBestSize(self): - """Overridden base class virtual. Determines the best size of the - button based on the label and bezel size.""" + """ + Overridden base class virtual. Determines the best size of the + button based on the label and bezel size. + """ w, h, useMin = self._GetLabelSize() defSize = wx.Button.GetDefaultSize() width = 12 + w @@ -133,6 +126,22 @@ class GenButton(wx.PyControl): return self.IsShown() and self.IsEnabled() + def GetDefaultAttributes(self): + """ + Overridden base class virtual. By default we should use + the same font/colour attributes as the native Button. + """ + return wx.Button.GetClassDefaultAttributes() + + + def ShouldInheritColours(self): + """ + Overridden base class virtual. Buttons usually don't inherit + the parent's colours. + """ + return False + + def Enable(self, enable=True): wx.PyControl.Enable(self, enable) self.Refresh() @@ -156,41 +165,43 @@ class GenButton(wx.PyControl): def InitColours(self): - faceClr = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE) - textClr = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNTEXT) - self.faceDnClr = faceClr - self.SetBackgroundColour(faceClr) - self.SetForegroundColour(textClr) - - shadowClr = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNSHADOW) - highlightClr = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNHIGHLIGHT) - self.shadowPen = wx.Pen(shadowClr, 1, wx.SOLID) - self.highlightPen = wx.Pen(highlightClr, 1, wx.SOLID) + """ + Calculate a new set of highlight and shadow colours based on + the background colour. Works okay if the colour is dark... + """ + faceClr = self.GetBackgroundColour() + r, g, b = faceClr.Get() + fr, fg, fb = min(255,r+32), min(255,g+32), min(255,b+32) + self.faceDnClr = wx.Colour(fr, fg, fb) + sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32) + self.shadowPen = wx.Pen(wx.Colour(sr,sg,sb), 1, wx.SOLID) + hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64) + self.highlightPen = wx.Pen(wx.Colour(hr,hg,hb), 1, wx.SOLID) + self.focusClr = wx.Colour(hr, hg, hb) + + textClr = self.GetForegroundColour() if wx.Platform == "__WXMAC__": self.focusIndPen = wx.Pen(textClr, 1, wx.SOLID) else: self.focusIndPen = wx.Pen(textClr, 1, wx.USER_DASH) self.focusIndPen.SetDashes([1,1]) self.focusIndPen.SetCap(wx.CAP_BUTT) - self.focusClr = highlightClr - - + + def SetBackgroundColour(self, colour): wx.PyControl.SetBackgroundColour(self, colour) - colour = self.GetBackgroundColour() + self.InitColours() - # Calculate a new set of highlight and shadow colours based on - # the new background colour. Works okay if the colour is dark... - r, g, b = colour.Get() - fr, fg, fb = min(255,r+32), min(255,g+32), min(255,b+32) - self.faceDnClr = wx.Colour(fr, fg, fb) - sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32) - self.shadowPen = wx.Pen(wx.Colour(sr,sg,sb), 1, wx.SOLID) - hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64) - self.highlightPen = wx.Pen(wx.Colour(hr,hg,hb), 1, wx.SOLID) - self.focusClr = wx.Colour(hr, hg, hb) + def SetForegroundColour(self, colour): + wx.PyControl.SetForegroundColour(self, colour) + self.InitColours() + def SetDefault(self): + tlw = wx.GetTopLevelParent(self) + if hasattr(tlw, 'SetDefaultItem'): + tlw.SetDefaultItem(self) + def _GetLabelSize(self): """ used internally """ w, h = self.GetTextExtent(self.GetLabel()) @@ -212,8 +223,8 @@ class GenButton(wx.PyControl): else: dc.SetPen(self.shadowPen) for i in range(self.bezelWidth): - dc.DrawLine((x1+i, y1), (x1+i, y2-i)) - dc.DrawLine((x1, y1+i), (x2-i, y1+i)) + dc.DrawLine(x1+i, y1, x1+i, y2-i) + dc.DrawLine(x1, y1+i, x2-i, y1+i) # draw the lower right sides if self.up: @@ -221,8 +232,8 @@ class GenButton(wx.PyControl): else: dc.SetPen(self.highlightPen) for i in range(self.bezelWidth): - dc.DrawLine((x1+i, y2-i), (x2+1, y2-i)) - dc.DrawLine((x2-i, y1+i), (x2-i, y2)) + dc.DrawLine(x1+i, y2-i, x2+1, y2-i) + dc.DrawLine(x2-i, y1+i, x2-i, y2) def DrawLabel(self, dc, width, height, dw=0, dy=0): @@ -235,43 +246,59 @@ class GenButton(wx.PyControl): tw, th = dc.GetTextExtent(label) if not self.up: dw = dy = self.labelDelta - dc.DrawText(label, ((width-tw)/2+dw, (height-th)/2+dy)) + dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dy) def DrawFocusIndicator(self, dc, w, h): bw = self.bezelWidth -## if self.hasFocus: -## self.focusIndPen.SetColour(self.GetForegroundColour()) -## else: -## #self.focusIndPen.SetColour(self.GetBackgroundColour()) -## self.focusIndPen.SetColour(self.GetForegroundColour()) self.focusIndPen.SetColour(self.focusClr) dc.SetLogicalFunction(wx.INVERT) dc.SetPen(self.focusIndPen) dc.SetBrush(wx.TRANSPARENT_BRUSH) - dc.DrawRectangle((bw+2,bw+2), (w-bw*2-4, h-bw*2-4)) + dc.DrawRectangle(bw+2,bw+2, w-bw*2-4, h-bw*2-4) dc.SetLogicalFunction(wx.COPY) - def OnPaint(self, event): (width, height) = self.GetClientSizeTuple() x1 = y1 = 0 x2 = width-1 y2 = height-1 - dc = wx.BufferedPaintDC(self) - if self.up: - dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID)) - else: - dc.SetBackground(wx.Brush(self.faceDnClr, wx.SOLID)) - dc.Clear() + + dc = wx.PaintDC(self) + brush = self.GetBackgroundBrush(dc) + if brush is not None: + dc.SetBackground(brush) + dc.Clear() + self.DrawBezel(dc, x1, y1, x2, y2) self.DrawLabel(dc, width, height) if self.hasFocus and self.useFocusInd: self.DrawFocusIndicator(dc, width, height) - def OnEraseBackground(self, event): - pass + def GetBackgroundBrush(self, dc): + if self.up: + colBg = self.GetBackgroundColour() + brush = wx.Brush(colBg, wx.SOLID) + if self.style & wx.BORDER_NONE: + myAttr = self.GetDefaultAttributes() + parAttr = self.GetParent().GetDefaultAttributes() + myDef = colBg == myAttr.colBg + parDef = self.GetParent().GetBackgroundColour() == parAttr.colBg + if myDef and parDef: + if wx.Platform == "__WXMAC__": + brush.MacSetTheme(1) # 1 == kThemeBrushDialogBackgroundActive + elif wx.Platform == "__WXMSW__": + if self.DoEraseBackground(dc): + brush = None + elif myDef and not parDef: + colBg = self.GetParent().GetBackgroundColour() + brush = wx.Brush(colBg, wx.SOLID) + else: + # this line assumes that a pressed button should be hilighted with + # a solid colour even if the background is supposed to be transparent + brush = wx.Brush(self.faceDnClr, wx.SOLID) + return brush def OnLeftDown(self, event): @@ -292,8 +319,9 @@ class GenButton(wx.PyControl): if not self.up: # if the button was down when the mouse was released... self.Notify() self.up = True - self.Refresh() - event.Skip() + if self: # in case the button was destroyed in the eventhandler + self.Refresh() + event.Skip() def OnMotion(self, event): @@ -315,29 +343,25 @@ class GenButton(wx.PyControl): def OnGainFocus(self, event): self.hasFocus = True - dc = wx.ClientDC(self) - w, h = self.GetClientSizeTuple() - if self.useFocusInd: - self.DrawFocusIndicator(dc, w, h) + self.Refresh() + self.Update() def OnLoseFocus(self, event): self.hasFocus = False - dc = wx.ClientDC(self) - w, h = self.GetClientSizeTuple() - if self.useFocusInd: - self.DrawFocusIndicator(dc, w, h) + self.Refresh() + self.Update() def OnKeyDown(self, event): - if self.hasFocus and event.KeyCode() == ord(" "): + if self.hasFocus and event.GetKeyCode() == ord(" "): self.up = False self.Refresh() event.Skip() def OnKeyUp(self, event): - if self.hasFocus and event.KeyCode() == ord(" "): + if self.hasFocus and event.GetKeyCode() == ord(" "): self.up = True self.Notify() self.Refresh() @@ -347,7 +371,9 @@ class GenButton(wx.PyControl): #---------------------------------------------------------------------- class GenBitmapButton(GenButton): - def __init__(self, parent, ID, bitmap, + """A generic bitmap button.""" + + def __init__(self, parent, id=-1, bitmap=wx.NullBitmap, pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0, validator = wx.DefaultValidator, name = "genbutton"): @@ -355,7 +381,7 @@ class GenBitmapButton(GenButton): self.bmpFocus = None self.bmpSelected = None self.SetBitmapLabel(bitmap) - GenButton.__init__(self, parent, ID, "", pos, size, style, validator, name) + GenButton.__init__(self, parent, id, "", pos, size, style, validator, name) def GetBitmapLabel(self): @@ -414,18 +440,19 @@ class GenBitmapButton(GenButton): if not self.up: dw = dy = self.labelDelta hasMask = bmp.GetMask() != None - dc.DrawBitmap(bmp, ((width-bw)/2+dw, (height-bh)/2+dy), hasMask) + dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, hasMask) #---------------------------------------------------------------------- -class GenBitmapTextButton(GenBitmapButton): # generic bitmapped button with Text Label - def __init__(self, parent, ID, bitmap, label, +class GenBitmapTextButton(GenBitmapButton): + """A generic bitmapped button with text label""" + def __init__(self, parent, id=-1, bitmap=wx.NullBitmap, label='', pos = wx.DefaultPosition, size = wx.DefaultSize, style = 0, validator = wx.DefaultValidator, name = "genbutton"): - GenBitmapButton.__init__(self, parent, ID, bitmap, pos, size, style, validator, name) + GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style, validator, name) self.SetLabel(label) @@ -474,10 +501,10 @@ class GenBitmapTextButton(GenBitmapButton): # generic bitmapped button with pos_x = (width-bw-tw)/2+dw # adjust for bitmap and text to centre if bmp !=None: - dc.DrawBitmap(bmp, (pos_x, (height-bh)/2+dy), hasMask) # draw bitmap if available + dc.DrawBitmap(bmp, pos_x, (height-bh)/2+dy, hasMask) # draw bitmap if available pos_x = pos_x + 2 # extra spacing from bitmap - dc.DrawText(label, (pos_x + dw+bw, (height-th)/2+dy)) # draw the text + dc.DrawText(label, pos_x + dw+bw, (height-th)/2+dy) # draw the text #---------------------------------------------------------------------- @@ -506,10 +533,10 @@ class __ToggleMixin: if not self.IsEnabled() or not self.HasCapture(): return if self.HasCapture(): - if self.up != self.saveUp: - self.Notify() self.ReleaseMouse() self.Refresh() + if self.up != self.saveUp: + self.Notify() def OnKeyDown(self, event): event.Skip() @@ -531,7 +558,7 @@ class __ToggleMixin: event.Skip() def OnKeyUp(self, event): - if self.hasFocus and event.KeyCode() == ord(" "): + if self.hasFocus and event.GetKeyCode() == ord(" "): self.up = not self.up self.Notify() self.Refresh() @@ -541,14 +568,48 @@ class __ToggleMixin: class GenToggleButton(__ToggleMixin, GenButton): + """A generic toggle button""" pass class GenBitmapToggleButton(__ToggleMixin, GenBitmapButton): + """A generic toggle bitmap button""" pass class GenBitmapTextToggleButton(__ToggleMixin, GenBitmapTextButton): + """A generic toggle bitmap button with text label""" pass #---------------------------------------------------------------------- +class ThemedGenButton(GenButton): + " A themed generic button, and base class for the other themed buttons " + def DrawBezel(self, dc, x1, y1, x2, y2): + rect = wx.Rect(x1, y1, x2, y2) + if self.up: + state = 0 + else: + state = wx.CONTROL_PRESSED + wx.RendererNative.Get().DrawPushButton(self, dc, rect, state) + +class ThemedGenBitmapButton(ThemedGenButton, GenBitmapButton): + """A themed generic bitmap button.""" + pass +class ThemedGenBitmapTextButton(ThemedGenButton, GenBitmapTextButton): + """A themed generic bitmapped button with text label""" + pass + +class ThemedGenToggleButton(ThemedGenButton, GenToggleButton): + """A themed generic toggle button""" + pass + +class ThemedGenBitmapToggleButton(ThemedGenButton, GenBitmapToggleButton): + """A themed generic toggle bitmap button""" + pass + +class ThemedGenBitmapTextToggleButton(ThemedGenButton, GenBitmapTextToggleButton): + """A themed generic toggle bitmap button with text label""" + pass + + +#----------------------------------------------------------------------