+++ /dev/null
-#----------------------------------------------------------------------
-# Name: wx.lib.buttons
-# Purpose: Various kinds of generic buttons, (not native controls but
-# self-drawn.)
-#
-# Author: Robin Dunn
-#
-# Created: 9-Dec-1999
-# RCS-ID: $Id$
-# 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. They act
-like normal buttons but you are able to better control how they look,
-bevel width, colours, etc.
-"""
-
-import wx
-import imageutils
-
-
-#----------------------------------------------------------------------
-
-class GenButtonEvent(wx.PyCommandEvent):
- """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
-
- def SetIsDown(self, isDown):
- self.isDown = isDown
-
- def GetIsDown(self):
- return self.isDown
-
- def SetButtonObj(self, btn):
- self.theButton = btn
-
- def GetButtonObj(self):
- return self.theButton
-
-
-#----------------------------------------------------------------------
-
-class GenButton(wx.PyControl):
- """A generic button, and base class for the other generic buttons."""
-
- labelDelta = 1
-
- def __init__(self, parent, id=-1, label='',
- pos = wx.DefaultPosition, size = wx.DefaultSize,
- style = 0, validator = wx.DefaultValidator,
- name = "genbutton"):
- cstyle = style
- if cstyle == 0:
- cstyle = wx.BORDER_NONE
- wx.PyControl.__init__(self, parent, id, pos, size, cstyle, validator, name)
-
- self.up = True
- self.hasFocus = False
- 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.InheritAttributes()
- self.SetInitialSize(size)
- self.InitColours()
-
- self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
- self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
- if wx.Platform == '__WXMSW__':
- self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDown)
- self.Bind(wx.EVT_MOTION, self.OnMotion)
- self.Bind(wx.EVT_SET_FOCUS, self.OnGainFocus)
- 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_PAINT, self.OnPaint)
-
-
- 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.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.
- """
- w, h, useMin = self._GetLabelSize()
- defSize = wx.Button.GetDefaultSize()
- width = 12 + w
- if useMin and width < defSize.width:
- width = defSize.width
- height = 11 + h
- if useMin and height < defSize.height:
- height = defSize.height
- width = width + self.bezelWidth - 1
- height = height + self.bezelWidth - 1
- return (width, height)
-
-
- def AcceptsFocus(self):
- """Overridden base class virtual."""
- 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 SetBezelWidth(self, width):
- """Set the width of the 3D effect"""
- self.bezelWidth = width
-
- def GetBezelWidth(self):
- """Return the width of the 3D effect"""
- return self.bezelWidth
-
- def SetUseFocusIndicator(self, flag):
- """Specifiy if a focus indicator (dotted line) should be used"""
- self.useFocusInd = flag
-
- def GetUseFocusIndicator(self):
- """Return focus indicator flag"""
- return self.useFocusInd
-
-
- def InitColours(self):
- """
- 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)
-
-
- def SetBackgroundColour(self, colour):
- wx.PyControl.SetBackgroundColour(self, colour)
- self.InitColours()
-
-
- 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())
- return w, h, True
-
-
- def Notify(self):
- evt = GenButtonEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
- evt.SetIsDown(not self.up)
- evt.SetButtonObj(self)
- evt.SetEventObject(self)
- self.GetEventHandler().ProcessEvent(evt)
-
-
- def DrawBezel(self, dc, x1, y1, x2, y2):
- # draw the upper left sides
- if self.up:
- dc.SetPen(self.highlightPen)
- 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)
-
- # draw the lower right sides
- if self.up:
- dc.SetPen(self.shadowPen)
- 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)
-
-
- def DrawLabel(self, dc, width, height, dw=0, dy=0):
- dc.SetFont(self.GetFont())
- if self.IsEnabled():
- dc.SetTextForeground(self.GetForegroundColour())
- else:
- dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
- label = self.GetLabel()
- tw, th = dc.GetTextExtent(label)
- if not self.up:
- dw = dy = self.labelDelta
- dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dy)
-
-
- def DrawFocusIndicator(self, dc, w, h):
- bw = self.bezelWidth
- 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.SetLogicalFunction(wx.COPY)
-
- def OnPaint(self, event):
- (width, height) = self.GetClientSizeTuple()
- x1 = y1 = 0
- x2 = width-1
- y2 = height-1
-
- 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 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):
- if not self.IsEnabled():
- return
- self.up = False
- self.CaptureMouse()
- self.SetFocus()
- self.Refresh()
- event.Skip()
-
-
- def OnLeftUp(self, event):
- if not self.IsEnabled() or not self.HasCapture():
- return
- if self.HasCapture():
- self.ReleaseMouse()
- if not self.up: # if the button was down when the mouse was released...
- self.Notify()
- self.up = True
- if self: # in case the button was destroyed in the eventhandler
- self.Refresh()
- event.Skip()
-
-
- def OnMotion(self, event):
- if not self.IsEnabled() or not self.HasCapture():
- return
- if event.LeftIsDown() and self.HasCapture():
- x,y = event.GetPositionTuple()
- w,h = self.GetClientSizeTuple()
- if self.up and x<w and x>=0 and y<h and y>=0:
- self.up = False
- self.Refresh()
- return
- if not self.up and (x<0 or y<0 or x>=w or y>=h):
- self.up = True
- self.Refresh()
- return
- event.Skip()
-
-
- def OnGainFocus(self, event):
- self.hasFocus = True
- self.Refresh()
- self.Update()
-
-
- def OnLoseFocus(self, event):
- self.hasFocus = False
- self.Refresh()
- self.Update()
-
-
- def OnKeyDown(self, event):
- if self.hasFocus and event.GetKeyCode() == ord(" "):
- self.up = False
- self.Refresh()
- event.Skip()
-
-
- def OnKeyUp(self, event):
- if self.hasFocus and event.GetKeyCode() == ord(" "):
- self.up = True
- self.Notify()
- self.Refresh()
- event.Skip()
-
-
-#----------------------------------------------------------------------
-
-class GenBitmapButton(GenButton):
- """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.bmpDisabled = None
- self.bmpFocus = None
- self.bmpSelected = None
- self.SetBitmapLabel(bitmap)
- GenButton.__init__(self, parent, id, "", pos, size, style, validator, name)
-
-
- def GetBitmapLabel(self):
- return self.bmpLabel
- def GetBitmapDisabled(self):
- return self.bmpDisabled
- def GetBitmapFocus(self):
- return self.bmpFocus
- def GetBitmapSelected(self):
- return self.bmpSelected
-
-
- def SetBitmapDisabled(self, bitmap):
- """Set bitmap to display when the button is disabled"""
- self.bmpDisabled = bitmap
-
- def SetBitmapFocus(self, bitmap):
- """Set bitmap to display when the button has the focus"""
- self.bmpFocus = bitmap
- self.SetUseFocusIndicator(False)
-
- def SetBitmapSelected(self, bitmap):
- """Set bitmap to display when the button is selected (pressed down)"""
- self.bmpSelected = bitmap
-
- def SetBitmapLabel(self, bitmap, createOthers=True):
- """
- Set the bitmap to display normally.
- This is the only one that is required. If
- createOthers is True, then the other bitmaps
- will be generated on the fly. Currently,
- only the disabled bitmap is generated.
- """
- self.bmpLabel = bitmap
- if bitmap is not None and createOthers:
- image = wx.ImageFromBitmap(bitmap)
- imageutils.grayOut(image)
- self.SetBitmapDisabled(wx.BitmapFromImage(image))
-
-
- def _GetLabelSize(self):
- """ used internally """
- if not self.bmpLabel:
- return -1, -1, False
- return self.bmpLabel.GetWidth()+2, self.bmpLabel.GetHeight()+2, False
-
- def DrawLabel(self, dc, width, height, dw=0, dy=0):
- bmp = self.bmpLabel
- if self.bmpDisabled and not self.IsEnabled():
- bmp = self.bmpDisabled
- if self.bmpFocus and self.hasFocus:
- bmp = self.bmpFocus
- if self.bmpSelected and not self.up:
- bmp = self.bmpSelected
- bw,bh = bmp.GetWidth(), bmp.GetHeight()
- if not self.up:
- dw = dy = self.labelDelta
- hasMask = bmp.GetMask() != None
- dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, hasMask)
-
-
-#----------------------------------------------------------------------
-
-
-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)
- self.SetLabel(label)
-
-
- def _GetLabelSize(self):
- """ used internally """
- w, h = self.GetTextExtent(self.GetLabel())
- if not self.bmpLabel:
- return w, h, True # if there isn't a bitmap use the size of the text
-
- w_bmp = self.bmpLabel.GetWidth()+2
- h_bmp = self.bmpLabel.GetHeight()+2
- width = w + w_bmp
- if h_bmp > h:
- height = h_bmp
- else:
- height = h
- return width, height, True
-
-
- def DrawLabel(self, dc, width, height, dw=0, dy=0):
- bmp = self.bmpLabel
- if bmp != None: # if the bitmap is used
- if self.bmpDisabled and not self.IsEnabled():
- bmp = self.bmpDisabled
- if self.bmpFocus and self.hasFocus:
- bmp = self.bmpFocus
- if self.bmpSelected and not self.up:
- bmp = self.bmpSelected
- bw,bh = bmp.GetWidth(), bmp.GetHeight()
- if not self.up:
- dw = dy = self.labelDelta
- hasMask = bmp.GetMask() != None
- else:
- bw = bh = 0 # no bitmap -> size is zero
-
- dc.SetFont(self.GetFont())
- if self.IsEnabled():
- dc.SetTextForeground(self.GetForegroundColour())
- else:
- dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT))
-
- label = self.GetLabel()
- tw, th = dc.GetTextExtent(label) # size of text
- if not self.up:
- dw = dy = self.labelDelta
-
- 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
- pos_x = pos_x + 2 # extra spacing from bitmap
-
- dc.DrawText(label, pos_x + dw+bw, (height-th)/2+dy) # draw the text
-
-
-#----------------------------------------------------------------------
-
-
-class __ToggleMixin:
- def SetToggle(self, flag):
- self.up = not flag
- self.Refresh()
- SetValue = SetToggle
-
- def GetToggle(self):
- return not self.up
- GetValue = GetToggle
-
- def OnLeftDown(self, event):
- if not self.IsEnabled():
- return
- self.saveUp = self.up
- self.up = not self.up
- self.CaptureMouse()
- self.SetFocus()
- self.Refresh()
-
- def OnLeftUp(self, event):
- if not self.IsEnabled() or not self.HasCapture():
- return
- if self.HasCapture():
- self.ReleaseMouse()
- self.Refresh()
- if self.up != self.saveUp:
- self.Notify()
-
- def OnKeyDown(self, event):
- event.Skip()
-
- def OnMotion(self, event):
- if not self.IsEnabled():
- return
- if event.LeftIsDown() and self.HasCapture():
- x,y = event.GetPositionTuple()
- w,h = self.GetClientSizeTuple()
- if x<w and x>=0 and y<h and y>=0:
- self.up = not self.saveUp
- self.Refresh()
- return
- if (x<0 or y<0 or x>=w or y>=h):
- self.up = self.saveUp
- self.Refresh()
- return
- event.Skip()
-
- def OnKeyUp(self, event):
- if self.hasFocus and event.GetKeyCode() == ord(" "):
- self.up = not self.up
- self.Notify()
- self.Refresh()
- 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
-
-#----------------------------------------------------------------------
-
-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
- if not self.IsEnabled():
- state = wx.CONTROL_DISABLED
- 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
-
-
-#----------------------------------------------------------------------