git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5768 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			418 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			418 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#----------------------------------------------------------------------
 | 
						|
# 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.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
 | 
						|
 | 
						|
#----------------------------------------------------------------------
 | 
						|
 | 
						|
 |