#---------------------------------------------------------------------- # Name: wxPython.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 #---------------------------------------------------------------------- """ This module implements various forms of generic buttons, meaning that they are not built on native controls but are self-drawn. The wxGenButton is the base. It acts like a normal button but you are able to better control how it looks, bevel width, colours, etc. wxGenBitmapButton is a button with one or more bitmaps that show the various states the button can be in. wxGenToggleButton stays depressed when clicked, until clicked again. wxGenBitmapToggleButton the same but with bitmaps. """ from wxPython.wx import * #---------------------------------------------------------------------- class wxGenButtonEvent(wxPyCommandEvent): def __init__(self, eventType, ID): wxPyCommandEvent.__init__(self, eventType, ID) self.isDown = false def SetIsDown(self, isDown): self.isDown = isDown def GetIsDown(self): return self.isDown #---------------------------------------------------------------------- class wxGenButton(wxWindow): def __init__(self, parent, ID, label, pos = wxDefaultPosition, size = wxDefaultSize, style = 0, validator = wxDefaultValidator, name = "genbutton"): wxWindow.__init__(self, parent, ID, pos, size, style, name) self.SetValidator(validator) self.up = true self.bezelWidth = 2 self.hasFocus = false self.useFocusInd = true self.SetLabel(label) self.SetPosition(pos) if type(size) == type(()): size = wxSize(size[0], size[1]) w = size.width h = size.height dsize = wxSize(75,23) ### wxButton_GetDefaultSize() if self.bezelWidth > 2: dsize.width = dsize.width + self.bezelWidth - 2 dsize.height = dsize.height + self.bezelWidth - 2 if w == -1: w = dsize.width if h == -1: h = dsize.height self.SetSize(wxSize(w,h)) font = parent.GetFont() if not font.Ok(): font = wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT) self.SetFont(font) self.InitColours() EVT_LEFT_DOWN(self, self.OnLeftDown) EVT_LEFT_UP(self, self.OnLeftUp) EVT_MOTION(self, self.OnMotion) EVT_SET_FOCUS(self, self.OnGainFocus) EVT_KILL_FOCUS(self, self.OnLoseFocus) EVT_KEY_DOWN(self, self.OnKeyDown) EVT_KEY_UP(self, self.OnKeyUp) 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): faceClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE) textClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT) self.SetBackgroundColour(faceClr) self.SetForegroundColour(textClr) shadowClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW) highlightClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT) self.shadowPen = wxPen(shadowClr, 1, wxSOLID) self.highlightPen = wxPen(highlightClr, 1, wxSOLID) self.focusIndPen = wxPen(textClr, 1, wxUSER_DASH) def Notify(self): evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId()) evt.SetIsDown(not self.up) 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(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT)) label = self.GetLabel() tw, th = dc.GetTextExtent(label) if not self.up: dw = dy = 1 dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dy) def DrawFocusIndicator(self, dc, w, h): bw = self.bezelWidth dc.SetLogicalFunction(wxINVERT) self.focusIndPen.SetColour(self.GetForegroundColour()) self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected... dc.SetPen(self.focusIndPen) dc.SetBrush(wxTRANSPARENT_BRUSH) dc.DrawRectangle(bw+2,bw+2, w-bw*2-4, h-bw*2-4) def OnPaint(self, event): (width, height) = self.GetClientSizeTuple() x1 = y1 = 0 x2 = width-1 y2 = height-1 dc = wxPaintDC(self) dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID)) 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 self.up = false self.CaptureMouse() self.SetFocus() self.Refresh() def OnLeftUp(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.ReleaseMouse() self.Refresh() def OnMotion(self, event): if not self.IsEnabled(): return if event.LeftIsDown(): x,y = event.GetPositionTuple() w,h = self.GetClientSizeTuple() if self.up and x=0 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 def OnGainFocus(self, event): self.hasFocus = true dc = wxClientDC(self) w, h = self.GetClientSizeTuple() if self.useFocusInd: self.DrawFocusIndicator(dc, w, h) def OnLoseFocus(self, event): self.hasFocus = false dc = wxClientDC(self) w, h = self.GetClientSizeTuple() if self.useFocusInd: self.DrawFocusIndicator(dc, w, h) def OnKeyDown(self, event): if self.hasFocus and event.KeyCode() == ord(" "): self.up = false self.Refresh() event.Skip() def OnKeyUp(self, event): if self.hasFocus and event.KeyCode() == ord(" "): self.up = true self.Notify() self.Refresh() event.Skip() #---------------------------------------------------------------------- class wxGenBitmapButton(wxGenButton): def __init__(self, parent, ID, bitmap, pos = wxDefaultPosition, size = wxDefaultSize, style = 0, validator = wxDefaultValidator, name = "genbutton"): wxGenButton.__init__(self, parent, ID, "", pos, size, style, validator, name) self.bmpLabel = bitmap self.bmpDisabled = None self.bmpFocus = None self.bmpSelected = None 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): self.bmpDisabled = bitmap def SetBitmapFocus(self, bitmap): self.bmpFocus = bitmap self.SetUseFocusIndicator(false) def SetBitmapSelected(self, bitmap): self.bmpSelected = bitmap def SetBitmapLabel(self, bitmap): self.bmpLabel = bitmap 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 = 1 dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, true) #---------------------------------------------------------------------- class __ToggleMixin: def OnLeftDown(self, event): if not self.IsEnabled(): return self.up = not self.up self.CaptureMouse() self.SetFocus() self.Refresh() def OnLeftUp(self, event): if not self.IsEnabled(): return self.Notify() self.ReleaseMouse() self.Refresh() def OnKeyDown(self, event): event.Skip() def OnKeyUp(self, event): if self.hasFocus and event.KeyCode() == ord(" "): self.up = not self.up self.Notify() self.Refresh() event.Skip() class wxGenToggleButton(__ToggleMixin, wxGenButton): pass class wxGenBitmapToggleButton(__ToggleMixin, wxGenBitmapButton): pass #----------------------------------------------------------------------