# 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
#----------------------------------------------------------------------
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
#----------------------------------------------------------------------
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.SetBestFittingSize(size)
self.InitColours()
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
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)
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.SetBestFittingSize(self, size)
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
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()
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):
+ self.GetParent().SetDefaultItem(self)
+
def _GetLabelSize(self):
""" used internally """
w, h = self.GetTextExtent(self.GetLabel())
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:
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):
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)
x1 = y1 = 0
x2 = width-1
y2 = height-1
- dc = wx.BufferedPaintDC(self)
+
+ dc = wx.PaintDC(self)
+ brush = None
+
if self.up:
- dc.SetBackground(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
+ 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:
- dc.SetBackground(wx.Brush(self.faceDnClr, wx.SOLID))
- dc.Clear()
+ brush = wx.Brush(self.faceDnClr, wx.SOLID)
+ 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 OnLeftDown(self, event):
if not self.IsEnabled():
return
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):
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):
#----------------------------------------------------------------------
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"):
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):
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)
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
#----------------------------------------------------------------------
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()
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
#----------------------------------------------------------------------