X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/299647acac7960652aadb008775429c1f8ea9b8d..c7c94fa73e72324ea26b3f000a70f5f731d36aec:/wxPython/demo/Joystick.py?ds=sidebyside
diff --git a/wxPython/demo/Joystick.py b/wxPython/demo/Joystick.py
index 2c4113adf0..c94e215507 100644
--- a/wxPython/demo/Joystick.py
+++ b/wxPython/demo/Joystick.py
@@ -1,206 +1,1107 @@
+#----------------------------------------------------------------------------
+# Name:        Joystick.py
+# Purpose:     Demonstrate use of wx.Joystick
+#
+# Author:      Jeff Grimmett (grimmtoo@softhome.net), adapted from original
+#              .wdr-derived demo
+#
+# Created:     02-Jan-2004
+# RCS-ID:      $Id$
+# Copyright:
+# Licence:     wxWindows license
+#----------------------------------------------------------------------------
+#
+
+import  math
+import  wx
+
+haveJoystick = True
+if wx.Platform == "__WXMAC__":
+    haveJoystick = False
 
 #----------------------------------------------------------------------------
 
-from wxPython.wx import *
-from joystick_wdr import *
+# Once all supported versions of Python support 32-bit integers on all
+# platforms, this can go up to 32.
+MAX_BUTTONS = 16
 
+#----------------------------------------------------------------------------
 
-class JoystickTestPanel(wxPanel):
-    def __init__(self, parent, id,
-        pos = wxDefaultPosition, size = wxDefaultSize,
-        style = wxTAB_TRAVERSAL ):
-        wxPanel.__init__(self, parent, id, pos, size, style)
+class Label(wx.StaticText):
+    # A derived StaticText that always aligns right and renders
+    # in a bold font.
+    def __init__(self, parent, label):
+        wx.StaticText.__init__(self, parent, -1, label, style=wx.ALIGN_RIGHT)
 
-        MakeJoystickTestPanel( self, True )
+        self.SetFont(
+            wx.Font(
+                parent.GetFont().GetPointSize(),
+                parent.GetFont().GetFamily(),
+                parent.GetFont().GetStyle(),
+                wx.BOLD
+                ))
 
-        try:
-            self.stick = wxJoystick()
-            self.stick.SetCapture(self)
-            EVT_JOYSTICK_EVENTS(self, self.OnJoystick)
-            self.UpdateFields()
-        except NotImplementedError, v:
-            wxMessageBox(str(v), "Exception Message")
+#----------------------------------------------------------------------------
+
+
+class JoyGauge(wx.Panel):
+    def __init__(self, parent, stick):
+
+        self.stick = stick
+        size = (100,100)
+        
+        wx.Panel.__init__(self, parent, -1, size=size)
+
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
+
+        self.buffer = wx.EmptyBitmap(*size)
+        dc = wx.BufferedDC(None, self.buffer)
+        self.DrawFace(dc)
+        self.DrawJoystick(dc)
+       
+
+    def OnSize(self, event):
+        # The face Bitmap init is done here, to make sure the buffer is always
+        # the same size as the Window
+        w, h  = self.GetClientSize()
+        self.buffer = wx.EmptyBitmap(w,h)
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawJoystick(dc)
+
+
+    def DrawFace(self, dc):
+        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+        dc.Clear()
+
+
+    def OnPaint(self, evt):
+        # When dc is destroyed it will blit self.buffer to the window,
+        # since no other drawing is needed we'll just return and let it
+        # do it's thing
+        dc = wx.BufferedPaintDC(self, self.buffer)
+
+
+    def DrawJoystick(self, dc):
+        # draw the guage as a maxed square in the center of this window.
+        w, h = self.GetClientSize()
+        edgeSize = min(w, h)
+
+        xorigin = (w - edgeSize) / 2
+        yorigin = (h - edgeSize) / 2
+        center = edgeSize / 2
+
+        # Restrict our drawing activities to the square defined
+        # above.
+        dc.SetClippingRegion(xorigin, yorigin, edgeSize, edgeSize)
+
+        # Optimize drawing a bit (for Win)
+        dc.BeginDrawing()
+
+        dc.SetBrush(wx.Brush(wx.Colour(251, 252, 237)))
+        dc.DrawRectangle(xorigin, yorigin, edgeSize, edgeSize)
+
+        dc.SetPen(wx.Pen(wx.BLACK, 1, wx.DOT_DASH))
+
+        dc.DrawLine(xorigin, yorigin + center, xorigin + edgeSize, yorigin + center)
+        dc.DrawLine(xorigin + center, yorigin, xorigin + center, yorigin + edgeSize)
+
+        if self.stick:
+            # Get the joystick position as a float
+            joyx =  float(self.stick.GetPosition().x)
+            joyy =  float(self.stick.GetPosition().y)
+
+            # Get the joystick range of motion
+            xmin = self.stick.GetXMin()
+            xmax = self.stick.GetXMax()
+            if xmin < 0:
+                xmax += abs(xmin)
+                joyx += abs(xmin)
+                xmin = 0
+            xrange = max(xmax - xmin, 1)
+
+            ymin = self.stick.GetYMin()
+            ymax = self.stick.GetYMax()
+            if ymin < 0:
+                ymax += abs(ymin)
+                joyy += abs(ymin)
+                ymin = 0
+            yrange = max(ymax - ymin, 1)
+
+            # calc a ratio of our range versus the joystick range
+            xratio = float(edgeSize) / xrange
+            yratio = float(edgeSize) / yrange
+
+            # calc the displayable value based on position times ratio
+            xval = int(joyx * xratio)
+            yval = int(joyy * yratio)
+
+            # and normalize the value from our brush's origin
+            x = xval + xorigin
+            y = yval + yorigin
+
+            # Now to draw it.
+            dc.SetPen(wx.Pen(wx.RED, 2))
+            dc.CrossHair(x, y)
+
+        # Turn off drawing optimization
+        dc.EndDrawing()
+
+
+    def Update(self):
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawJoystick(dc)
+
+
+#----------------------------------------------------------------------------
+
+class JoyPanel(wx.Panel):
+    def __init__(self, parent, stick):
+
+        self.stick = stick
+
+        wx.Panel.__init__(self, parent, -1)
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        fn = wx.Font(
+                parent.GetFont().GetPointSize() + 3,
+                parent.GetFont().GetFamily(),
+                parent.GetFont().GetStyle(),
+                wx.BOLD
+                )
+
+        t = wx.StaticText(self, -1, "X - Y Axes", style = wx.ALIGN_CENTRE)
+        t.SetFont(fn)
+        sizer.Add(t, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTER_HORIZONTAL, 1)
+
+        self.control = JoyGauge(self, self.stick)
+        sizer.Add(self.control, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTER_HORIZONTAL, 1)
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def Update(self):
+        self.control.Update()
+
+
+#----------------------------------------------------------------------------
+
+class POVGauge(wx.Panel):
+    #
+    # Display the current postion of the POV control
+    #
+    def __init__(self, parent, stick):
+
+        self.stick = stick
+        self.size = (100, 100)
+        self.avail = False
+        self.fourDir = False
+        self.cts = False
+
+        wx.Panel.__init__(self, parent, -1, size=self.size)
+
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
+
+        self.buffer = wx.EmptyBitmap(*self.size)
+        dc = wx.BufferedDC(None, self.buffer)
+        self.DrawFace(dc)
+        self.DrawPOV(dc)
+
+
+    def OnSize(self, event):
+        # calculate the size of our display and make a buffer for it.
+        w, h  = self.GetClientSize()
+        s = min(w, h)
+        self.size = (s, s)
+        self.buffer = wx.EmptyBitmap(w,h)
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawPOV(dc)
+
+    
+    def DrawFace(self, dc):
+        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+        dc.Clear()
+
+
+    def OnPaint(self, evt):
+        # When dc is destroyed it will blit self.buffer to the window,
+        # since no other drawing is needed we'll just return and let it
+        # do it's thing
+        dc = wx.BufferedPaintDC(self, self.buffer)
+
+
+    def DrawPOV(self, dc):
+        # draw the guage as a maxed circle in the center of this window.
+        w, h = self.GetClientSize()
+        diameter = min(w, h)
 
+        xorigin = (w - diameter) / 2
+        yorigin = (h - diameter) / 2
+        xcenter = xorigin + diameter / 2
+        ycenter = yorigin + diameter / 2
 
-    def UpdateFields(self):
+        # Optimize drawing a bit (for Win)
+        dc.BeginDrawing()
+
+        # our 'raster'.
+        dc.SetBrush(wx.Brush(wx.WHITE))
+        dc.DrawCircle(xcenter, ycenter, diameter/2)
+        dc.SetBrush(wx.Brush(wx.BLACK))
+        dc.DrawCircle(xcenter, ycenter, 10)
+
+        # fancy decorations
+        dc.SetPen(wx.Pen(wx.BLACK, 1, wx.DOT_DASH))
+        dc.DrawLine(xorigin, ycenter, xorigin + diameter, ycenter)
+        dc.DrawLine(xcenter, yorigin, xcenter, yorigin + diameter)
+
+        if self.stick:
+            if self.avail:
+
+                pos = -1
+
+                # use the appropriate function to get the POV position
+                if self.fourDir:
+                    pos = self.stick.GetPOVPosition()
+
+                if self.cts:
+                    pos = self.stick.GetPOVCTSPosition()
+
+                # trap invalid values
+                if 0 <= pos <= 36000:
+                    vector = 30
+                else:
+                    vector = 0
+
+                # rotate CCW by 90 so that 0 is up.
+                pos = (pos / 100) - 90
+
+                # Normalize
+                if pos < 0:
+                    pos = pos + 360
+
+                # Stolen from wx.lib.analogclock :-)
+                radiansPerDegree = math.pi / 180
+                pointX = int(round(vector * math.cos(pos * radiansPerDegree)))
+                pointY = int(round(vector * math.sin(pos * radiansPerDegree)))
+
+                # normalise value to match our actual center.
+                nx = pointX + xcenter
+                ny = pointY + ycenter
+
+                # Draw the line
+                dc.SetPen(wx.Pen(wx.BLUE, 2))
+                dc.DrawLine(xcenter, ycenter, nx, ny)
+
+                # And a little thing to show the endpoint
+                dc.SetBrush(wx.Brush(wx.BLUE))
+                dc.DrawCircle(nx, ny, 8)
+
+        # Turn off drawing optimization
+        dc.EndDrawing()
+
+
+    def Update(self):
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawPOV(dc)
+
+
+    def Calibrate(self):
         s = self.stick
-        self.GetXPositionCtrl().SetValue(str(s.GetPosition().x))
-        self.GetYPositionCtrl().SetValue(str(s.GetPosition().y))
-        self.GetZPositionCtrl().SetValue(str(s.GetZPosition()))
-        self.GetPovCtsPosCtrl().SetValue(str(s.GetPOVPosition()))
-        self.GetRudderPosCtrl().SetValue(str(s.GetRudderPosition()))
-        self.GetHasRudderCtrl().SetValue(str(s.HasRudder()))
-        self.GetHasZCtrl().SetValue(str(s.HasZ()))
-        self.GetHasPovCtrl().SetValue(str(s.HasPOV()))
-        self.GetHasPov4dirCtrl().SetValue(str(s.HasPOV4Dir()))
-        self.GetMfgIdCtrl().SetValue(str(s.GetManufacturerId()))
-        self.GetProdNameCtrl().SetValue(str(s.GetProductName()))
-        self.GetZMinCtrl().SetValue(str(s.GetZMin()))
-        self.GetXMaxCtrl().SetValue(str(s.GetXMax()))
-        self.GetNumButtonsCtrl().SetValue(str(s.GetNumberButtons()))
-        self.GetNumAxesCtrl().SetValue(str(s.GetNumberAxes()))
-        self.GetPollingMinCtrl().SetValue(str(s.GetPollingMin()))
-        self.GetPollingMaxCtrl().SetValue(str(s.GetPollingMax()))
-        self.GetUMinCtrl().SetValue(str(s.GetUMin()))
-        self.GetUMaxCtrl().SetValue(str(s.GetUMax()))
-        self.GetButtonStateCtrl().SetValue(str(s.GetButtonState()))
-        self.GetPovPositionCtrl().SetValue(str(s.GetPOVPosition()))
-        self.GetUPositionCtrl().SetValue(str(s.GetUPosition()))
-        self.GetVPositionCtrl().SetValue(str(s.GetVPosition()))
-        self.GetHasUCtrl().SetValue(str(s.HasU()))
-        self.GetHasVCtrl().SetValue(str(s.HasV()))
-        self.GetHasPovCtsCtrl().SetValue(str(s.HasPOVCTS()))
-        self.GetNumSticksCtrl().SetValue(str(s.GetNumberJoysticks()))
-        self.GetXMinCtrl().SetValue(str(s.GetXMin()))
-        self.GetYMinCtrl().SetValue(str(s.GetYMin()))
-        self.GetYMaxCtrl().SetValue(str(s.GetYMax()))
-        self.GetZMaxCtrl().SetValue(str(s.GetZMax()))
-        self.GetMaxButtonsCtrl().SetValue(str(s.GetMaxButtons()))
-        self.GetMaxAxesCtrl().SetValue(str(s.GetMaxAxes()))
-        self.GetRudderMinCtrl().SetValue(str(s.GetRudderMin()))
-        self.GetRudderMaxCtrl().SetValue(str(s.GetRudderMax()))
-        self.GetVMinCtrl().SetValue(str(s.GetVMin()))
-        self.GetVMaxCtrl().SetValue(str(s.GetVMax()))
+        self.avail = s.HasPOV()
+        self.fourDir = s.HasPOV4Dir()
+        self.cts = s.HasPOVCTS()
 
 
-    def OnJoystick(self, evt):
-        self.UpdateFields()
+#----------------------------------------------------------------------------
+
+class POVStatus(wx.Panel):
+    #
+    # Displays static info about the POV control
+    #
+    def __init__(self, parent, stick):
 
+        self.stick = stick
 
-    # WDR: methods for JoystickTestPanel
+        wx.Panel.__init__(self, parent, -1, size=(100, 100))
 
-    def GetYPositionCtrl(self):
-        return self.FindWindowById(ID_Y_Position_Ctrl)
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        sizer.Add((20,20))
+        
+        self.avail = wx.CheckBox(self, -1, "Available")
+        sizer.Add(self.avail, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2)
 
-    def GetXPositionCtrl(self):
-        return self.FindWindowById(ID_X_Position_Ctrl)
+        self.fourDir = wx.CheckBox(self, -1, "4-Way Only")
+        sizer.Add(self.fourDir, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2)
 
+        self.cts = wx.CheckBox(self, -1, "Continuous")
+        sizer.Add(self.cts, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2)
 
-    def GetVMaxCtrl(self):
-        return self.FindWindowById(ID_V_Max_Ctrl)
+        self.SetSizer(sizer)
+        sizer.Fit(self)
 
-    def GetVMinCtrl(self):
-        return self.FindWindowById(ID_V_Min_Ctrl)
+        # Effectively makes the checkboxes read-only.
+        self.Bind(wx.EVT_CHECKBOX, self.Calibrate)
 
-    def GetRudderMaxCtrl(self):
-        return self.FindWindowById(ID_Rudder_Max_Ctrl)
 
-    def GetRudderMinCtrl(self):
-        return self.FindWindowById(ID_Rudder_Min_Ctrl)
+    def Calibrate(self, evt=None):
+        s = self.stick
+        self.avail.SetValue(s.HasPOV())
+        self.fourDir.SetValue(s.HasPOV4Dir())
+        self.cts.SetValue(s.HasPOVCTS())
 
-    def GetMaxAxesCtrl(self):
-        return self.FindWindowById(ID_Max_Axes_Ctrl)
 
-    def GetMaxButtonsCtrl(self):
-        return self.FindWindowById(ID_Max_Buttons_Ctrl)
+#----------------------------------------------------------------------------
 
-    def GetZMaxCtrl(self):
-        return self.FindWindowById(ID_Z_Max_Ctrl)
+class POVPanel(wx.Panel):
+    def __init__(self, parent, stick):
 
-    def GetYMaxCtrl(self):
-        return self.FindWindowById(ID_Y_Max_Ctrl)
+        self.stick = stick
 
-    def GetYMinCtrl(self):
-        return self.FindWindowById(ID_Y_Min_Ctrl)
+        wx.Panel.__init__(self, parent, -1, size=(100, 100))
 
-    def GetXMinCtrl(self):
-        return self.FindWindowById(ID_X_Min_Ctrl)
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        gsizer = wx.BoxSizer(wx.VERTICAL)
 
-    def GetNumSticksCtrl(self):
-        return self.FindWindowById(ID_Num_Sticks_Ctrl)
+        sizer.Add((25,25))
+        
+        fn = wx.Font(
+                parent.GetFont().GetPointSize() + 3,
+                parent.GetFont().GetFamily(),
+                parent.GetFont().GetStyle(),
+                wx.BOLD
+                )
+        t = wx.StaticText(self, -1, "POV Control", style = wx.ALIGN_CENTER)
+        t.SetFont(fn)
+        gsizer.Add(t, 0, wx.ALL | wx.EXPAND, 1)
+        
+        self.display = POVGauge(self, stick)
+        gsizer.Add(self.display, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1)
+        sizer.Add(gsizer, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1)
+        
+        self.status = POVStatus(self, stick)
+        sizer.Add(self.status, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1)
 
-    def GetHasPovCtsCtrl(self):
-        return self.FindWindowById(ID_Has_POV_CTS_Ctrl)
+        self.SetSizer(sizer)
+        sizer.Fit(self)
 
-    def GetHasVCtrl(self):
-        return self.FindWindowById(ID_Has_V_Ctrl)
 
-    def GetHasUCtrl(self):
-        return self.FindWindowById(ID_Has_U_Ctrl)
+    def Calibrate(self):
+        self.display.Calibrate()
+        self.status.Calibrate()
 
-    def GetVPositionCtrl(self):
-        return self.FindWindowById(ID_V_Position_Ctrl)
 
-    def GetUPositionCtrl(self):
-        return self.FindWindowById(ID_U_Position_Ctrl)
+    def Update(self):
+        self.display.Update()
 
-    def GetPovPositionCtrl(self):
-        return self.FindWindowById(ID_POV_Position_Ctrl)
 
-    def GetButtonStateCtrl(self):
-        return self.FindWindowById(ID_Button_State_Ctrl)
+#----------------------------------------------------------------------------
 
-    def GetUMaxCtrl(self):
-        return self.FindWindowById(ID_U_Max_Ctrl)
+class LED(wx.Panel):
+    def __init__(self, parent, number):
 
-    def GetUMinCtrl(self):
-        return self.FindWindowById(ID_U_Min_Ctrl)
+        self.state = -1
+        self.size = (20, 20)
+        self.number = number
 
-    def GetPollingMaxCtrl(self):
-        return self.FindWindowById(ID_Polling_Max_Ctrl)
+        self.fn = wx.Font(
+                parent.GetFont().GetPointSize() - 1,
+                parent.GetFont().GetFamily(),
+                parent.GetFont().GetStyle(),
+                wx.BOLD
+                )
 
-    def GetPollingMinCtrl(self):
-        return self.FindWindowById(ID_Polling_Min_Ctrl)
+        wx.Panel.__init__(self, parent, -1, size=self.size)
 
-    def GetNumAxesCtrl(self):
-        return self.FindWindowById(ID_Num_Axes_Ctrl)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
 
-    def GetNumButtonsCtrl(self):
-        return self.FindWindowById(ID_Num_Buttons_Ctrl)
+        self.buffer = wx.EmptyBitmap(*self.size)
+        dc = wx.BufferedDC(None, self.buffer)
+        self.DrawFace(dc)
+        self.DrawLED(dc)
 
-    def GetXMaxCtrl(self):
-        return self.FindWindowById(ID_X_Max_Ctrl)
 
-    def GetZMinCtrl(self):
-        return self.FindWindowById(ID_Z_Min_Ctrl)
+    def OnSize(self, event):
+        # calculate the size of our display.
+        w, h  = self.GetClientSize()
+        s = min(w, h)
+        self.size = (s, s)
+        self.buffer = wx.EmptyBitmap(*self.size)
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawLED(dc)
 
-    def GetProdNameCtrl(self):
-        return self.FindWindowById(ID_Prod_Name_Ctrl)
 
-    def GetMfgIdCtrl(self):
-        return self.FindWindowById(ID_Mfg_ID_Ctrl)
+    def DrawFace(self, dc):
+        dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+        dc.Clear()
 
-    def GetHasPov4dirCtrl(self):
-        return self.FindWindowById(ID_Has_POV_4DIR_Ctrl)
 
-    def GetHasPovCtrl(self):
-        return self.FindWindowById(ID_Has_POV_Ctrl)
+    def OnPaint(self, evt):
+        # When dc is destroyed it will blit self.buffer to the window,
+        # since no other drawing is needed we'll just return and let it
+        # do it's thing
+        dc = wx.BufferedPaintDC(self, self.buffer)
 
-    def GetHasZCtrl(self):
-        return self.FindWindowById(ID_Has_Z_Ctrl)
 
-    def GetHasRudderCtrl(self):
-        return self.FindWindowById(ID_Has_Rudder_Ctrl)
+    def DrawLED(self, dc):
+        # bitmap size
+        bw, bh = self.size
 
-    def GetRudderPosCtrl(self):
-        return self.FindWindowById(ID_Rudder_Pos_Ctrl)
+        # center of bitmap
+        center = bw / 2
 
-    def GetPovCtsPosCtrl(self):
-        return self.FindWindowById(ID_POV_CTS_Pos_Ctrl)
+        # calc the 0, 0 origin of the bitmap
+        xorigin = center - (bw / 2)
+        yorigin = center - (bh / 2)
 
-    def GetZPositionCtrl(self):
-        return self.FindWindowById(ID_Z_Position_Ctrl)
+        # Optimize drawing a bit (for Win)
+        dc.BeginDrawing()
 
-    # WDR: handler implementations for JoysticktestPanel
+        # our 'raster'.
+        if self.state == 0:
+            dc.SetBrush(wx.Brush(wx.RED))
+        elif self.state == 1:
+            dc.SetBrush(wx.Brush(wx.GREEN))
+        else:
+            dc.SetBrush(wx.Brush(wx.BLACK))
 
+        dc.DrawCircle(center, center, bw/2)
 
-#----------------------------------------------------------------------
+        txt = str(self.number)
 
-def runTest(frame, nb, log):
-    win = JoystickTestPanel(nb, -1)
-    return win
+        # Set the font for the DC ...
+        dc.SetFont(self.fn)
+        # ... and calculate how much space our value
+        # will take up.
+        fw, fh = dc.GetTextExtent(txt)
+
+        # Calc the center of the LED, and from that
+        # derive the origin of our value.
+        tx = center - (fw/2)
+        ty = center - (fh/2)
+
+        # I draw the value twice so as to give it a pseudo-shadow.
+        # This is (mostly) because I'm too lazy to figure out how
+        # to blit my text onto the gauge using one of the logical
+        # functions. The pseudo-shadow gives the text contrast
+        # regardless of whether the bar is under it or not.
+        dc.SetTextForeground(wx.WHITE)
+        dc.DrawText(txt, tx, ty)
+
+        # Turn off drawing optimization
+        dc.EndDrawing()
+
+
+    def Update(self):
+        dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+        self.DrawFace(dc)
+        self.DrawLED(dc)
+
+
+#----------------------------------------------------------------------------
+
+class JoyButtons(wx.Panel):
+    def __init__(self, parent, stick):
+
+        self.stick = stick
+        self.leds = {}
+
+        wx.Panel.__init__(self, parent, -1)
+
+        tsizer = wx.BoxSizer(wx.VERTICAL)
+
+        fn = wx.Font(
+                parent.GetFont().GetPointSize() + 3,
+                parent.GetFont().GetFamily(),
+                parent.GetFont().GetStyle(),
+                wx.BOLD
+                )
+
+        t = wx.StaticText(self, -1, "Buttons", style = wx.ALIGN_LEFT)
+        t.SetFont(fn)
+        tsizer.Add(t, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 1)
+
+        sizer = wx.FlexGridSizer(4, 16, 2, 2)
+
+        fn.SetPointSize(parent.GetFont().GetPointSize() + 1)
+
+        for i in range(0, MAX_BUTTONS):
+            t = LED(self, i)
+            self.leds[i] = t
+            sizer.Add(t, 1, wx.ALL|wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL, 1)
+            sizer.AddGrowableCol(i)
+
+        tsizer.Add(sizer, 1, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 1)
+
+        self.SetSizer(tsizer)
+        tsizer.Fit(self)
+
+    def Calibrate(self):
+        for i in range(0, MAX_BUTTONS):
+            self.leds[i].state = -1
+
+        t = self.stick.GetNumberButtons()
+
+        for i in range(0, t):
+            self.leds[i].state = 0
+
+    def Update(self):
+        t = self.stick.GetButtonState()
+
+        for i in range(0, MAX_BUTTONS):
+            if self.leds[i].state == 1:
+                self.leds[i].state = 0
+
+            if (t & (1<
+
+wx.Joystick
+This demo illustrates the use of the wx.Joystick class, which is an interface to
+one or more joysticks attached to your system.
+
+
The data that can be retrieved from the joystick comes in four basic flavors. +All of these are illustrated in the demo. In fact, this demo illustrates everything +you can get from the wx.Joystick control. + +
Getting data from the joystick can be event-driven thanks to four event types associated +with wx.JoystickEvent, or the joystick can be polled programatically to get data on +a regular basis. + +
+ # assume buttonState is what the stick returned, and buttonBit + # is the bit you want to examine + + if (buttonState & ( 1 << buttonBit )) : + # button pressed, do something with it ++ +
The problem here is that some OSs return a 32-bit value for up to 32 buttons +(imagine that stick!). Python V2.3 will generate an exception for bit +values over 30. For that reason, this demo is limited to 16 buttons. + +
Note that more than one button can be pressed at a time, so be sure to check all of them! + + +
Different methods are provided to retrieve the POV data for a CTS hat +versus a four-way hat. + +
Fortunately, there is an easy workaround. In the top level frame, create a wx.Timer +that will poll the stick at a set interval. Of course, if you do this, you might as +well forgo catching wxEVT_JOYSTICK_* events at all and rely on the timer to do the +polling. + +
Ideally, the timer should be a one-shot; after it fires, collect and process data as +needed, then re-start the timer, possibly using wx.CallAfter(). + + +