-#----------------------------------------------------------------------
-# 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
- 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 wxGenButton(wxControl):
- def __init__(self, parent, ID, label,
- pos = wxDefaultPosition, size = wxDefaultSize,
- style = 0, validator = wxDefaultValidator,
- name = "genbutton"):
- if style == 0:
- style = wxNO_BORDER
- wxControl.__init__(self, parent, ID, pos, size, style, validator, name)
-
- self.up = true
- self.bezelWidth = 2
- self.hasFocus = false
- self.useFocusInd = true
-
- self.SetLabel(label)
- self.SetPosition(pos)
- font = parent.GetFont()
- if not font.Ok():
- font = wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT)
- self.SetFont(font)
- self.SetBestSize(size)
- 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 SetBestSize(self, size=None):
- """
- Given the current font and bezel width settings, calculate
- and set a good size.
- """
- if size is None:
- size = wxSize(-1,-1)
- if type(size) == type(()):
- size = wxSize(size[0], size[1])
-
- # make a new size so we don't mess with the one passed in
- size = wxSize(size.width, size.height)
-
- w, h, useMin = self._GetLabelSize()
- defSize = wxButton_GetDefaultSize()
- if size.width == -1:
- size.width = 12 + w
- if useMin and size.width < defSize.width:
- size.width = defSize.width
- if size.height == -1:
- size.height = 11 + h
- if useMin and size.height < defSize.height:
- size.height = defSize.height
-
- size.width = size.width + self.bezelWidth - 1
- size.height = size.height + self.bezelWidth - 1
-
- self.SetSize(size)
-
-
- 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.faceDnClr = faceClr
- 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)
- self.focusIndPen = wxPen(textClr, 1, wxDOT)
-
-
- def SetBackgroundColour(self, colour):
- wxWindow.SetBackgroundColour(self, colour)
-
- # 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 = wxColour(fr, fg, fb)
- sr, sg, sb = max(0,r-32), max(0,g-32), max(0,b-32)
- self.shadowPen = wxPen(wxColour(sr,sg,sb), 1, wxSOLID)
- hr, hg, hb = min(255,r+64), min(255,g+64), min(255,b+64)
- self.highlightPen = wxPen(wxColour(hr,hg,hb), 1, wxSOLID)
-
-
- def _GetLabelSize(self):
- """ used internally """
- w, h = self.GetTextExtent(self.GetLabel())
- return w, h, true
-
-
- def Notify(self):
- evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
- evt.SetIsDown(not self.up)
- evt.SetButtonObj(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(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)
- if self.up:
- dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID))
- else:
- dc.SetBackground(wxBrush(self.faceDnClr, 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<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
-
-
- 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"):
- self.bmpLabel = bitmap
- self.bmpDisabled = None
- self.bmpFocus = None
- self.bmpSelected = None
- wxGenButton.__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):
- """Set the bitmap to display normally. This is the only one that is required."""
- self.bmpLabel = bitmap
-
-
- 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 = 1
- hasMask = bmp.GetMask() != None
- dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, hasMask)
-
-
-
-#----------------------------------------------------------------------
-
-
-class __ToggleMixin:
- def SetToggle(self, flag):
- self.up = not flag
-
- def GetToggle(self):
- return not self.up
-
- 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():
- return
- if self.up != self.saveUp:
- 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
-
-#----------------------------------------------------------------------
-
-