]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/demo/Joystick.py
move wxPython to new trunk
[wxWidgets.git] / wxPython / demo / Joystick.py
diff --git a/wxPython/demo/Joystick.py b/wxPython/demo/Joystick.py
deleted file mode 100644 (file)
index c94e215..0000000
+++ /dev/null
@@ -1,1107 +0,0 @@
-#----------------------------------------------------------------------------
-# 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
-
-#----------------------------------------------------------------------------
-
-# Once all supported versions of Python support 32-bit integers on all
-# platforms, this can go up to 32.
-MAX_BUTTONS = 16
-
-#----------------------------------------------------------------------------
-
-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)
-
-        self.SetFont(
-            wx.Font(
-                parent.GetFont().GetPointSize(),
-                parent.GetFont().GetFamily(),
-                parent.GetFont().GetStyle(),
-                wx.BOLD
-                ))
-
-#----------------------------------------------------------------------------
-
-
-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
-
-        # 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.avail = s.HasPOV()
-        self.fourDir = s.HasPOV4Dir()
-        self.cts = s.HasPOVCTS()
-
-
-#----------------------------------------------------------------------------
-
-class POVStatus(wx.Panel):
-    #
-    # Displays static info about the POV control
-    #
-    def __init__(self, parent, stick):
-
-        self.stick = stick
-
-        wx.Panel.__init__(self, parent, -1, size=(100, 100))
-
-        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)
-
-        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)
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-        # Effectively makes the checkboxes read-only.
-        self.Bind(wx.EVT_CHECKBOX, self.Calibrate)
-
-
-    def Calibrate(self, evt=None):
-        s = self.stick
-        self.avail.SetValue(s.HasPOV())
-        self.fourDir.SetValue(s.HasPOV4Dir())
-        self.cts.SetValue(s.HasPOVCTS())
-
-
-#----------------------------------------------------------------------------
-
-class POVPanel(wx.Panel):
-    def __init__(self, parent, stick):
-
-        self.stick = stick
-
-        wx.Panel.__init__(self, parent, -1, size=(100, 100))
-
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        gsizer = wx.BoxSizer(wx.VERTICAL)
-
-        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)
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-
-    def Calibrate(self):
-        self.display.Calibrate()
-        self.status.Calibrate()
-
-
-    def Update(self):
-        self.display.Update()
-
-
-#----------------------------------------------------------------------------
-
-class LED(wx.Panel):
-    def __init__(self, parent, number):
-
-        self.state = -1
-        self.size = (20, 20)
-        self.number = number
-
-        self.fn = wx.Font(
-                parent.GetFont().GetPointSize() - 1,
-                parent.GetFont().GetFamily(),
-                parent.GetFont().GetStyle(),
-                wx.BOLD
-                )
-
-        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.DrawLED(dc)
-
-
-    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 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 DrawLED(self, dc):
-        # bitmap size
-        bw, bh = self.size
-
-        # center of bitmap
-        center = bw / 2
-
-        # calc the 0, 0 origin of the bitmap
-        xorigin = center - (bw / 2)
-        yorigin = center - (bh / 2)
-
-        # Optimize drawing a bit (for Win)
-        dc.BeginDrawing()
-
-        # 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)
-
-        # 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<<i)):
-                self.leds[i].state = 1
-
-            self.leds[i].Update()
-
-
-#----------------------------------------------------------------------------
-
-class InfoPanel(wx.Panel):
-    def __init__(self, parent, stick):
-
-        self.stick = stick
-
-        wx.Panel.__init__(self, parent, -1)
-
-        sizer = wx.GridBagSizer(1, 1)
-
-        sizer.Add(Label(self, 'Mfr ID: '), (0, 0), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.MfgID = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.MfgID, (0, 1), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        sizer.Add(Label(self, 'Prod Name: '), (0, 2), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.ProdName = wx.TextCtrl(self, -1, value='', style=wx.TE_READONLY)
-        sizer.Add(self.ProdName, (0, 3), (1, 3), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        sizer.Add(Label(self, 'Threshold: '), (0, 6), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.Threshold = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.Threshold, (0, 7), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        #----------------------------------------------------------------------------
-        b = wx.Button(self, -1, "Calibrate")
-        sizer.Add(b, (1, 0), (2, 2), wx.ALL | wx.ALIGN_CENTER, 2)
-
-        sizer.Add(Label(self, '# of Sticks: '), (1, 2), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.NumJoysticks = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.NumJoysticks, (1, 3), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        sizer.Add(Label(self, '# of Axes: '), (1, 4), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.NumAxis = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.NumAxis, (1, 5), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        sizer.Add(Label(self, 'Max # Axes: '), (1, 6), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.MaxAxis = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.MaxAxis, (1, 7), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        #----------------------------------------------------------------------------
-
-        sizer.Add(Label(self, 'Polling -- '), (2, 3), (1, 1), wx.ALL | wx.GROW, 2)
-
-        sizer.Add(Label(self, 'Min: '), (2, 4), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.PollMin = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.PollMin, (2, 5), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        sizer.Add(Label(self, 'Max: '), (2, 6), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_RIGHT, 2)
-        self.PollMax = wx.TextCtrl(self, -1, value='', size=(45, -1), style=wx.TE_READONLY)
-        sizer.Add(self.PollMax, (2, 7), (1, 1), wx.ALL | wx.GROW | wx.ALIGN_LEFT, 2)
-
-        #----------------------------------------------------------------------------
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-
-    def Calibrate(self):
-        if not self.stick:
-            return
-
-        s = self.stick
-
-        self.MfgID.SetValue(str(s.GetManufacturerId()))
-        self.ProdName.SetValue(str(s.GetProductName()))
-        self.Threshold.SetValue(str(s.GetMovementThreshold()))
-        self.NumJoysticks.SetValue(str(s.GetNumberJoysticks()))
-        self.NumAxis.SetValue(str(s.GetNumberAxes()))
-        self.MaxAxis.SetValue(str(s.GetMaxAxes()))
-        self.PollMin.SetValue(str(s.GetPollingMin()))
-        self.PollMax.SetValue(str(s.GetPollingMax()))
-
-
-#----------------------------------------------------------------------------
-
-class AxisBar(wx.Gauge):
-    #
-    # This class allows us to use a wx.Gauge to display the axis value
-    # with a fancy label overlayed onto the guage itself. Two values are
-    # used to do things: first of all, since the gauge is limited to
-    # positive numbers, the scale is fixed at 0 to 1000. We will receive
-    # an adjusted value to use to render the gauge itself. The other value
-    # is a raw value and actually reflects the value from the joystick itself,
-    # which is then drawn over the gauge.
-    #
-    def __init__(self, parent):
-        wx.Gauge.__init__(self, parent, -1, 1000, size=(-1, 20), style = wx.GA_HORIZONTAL | wx.GA_SMOOTH )
-
-        # This is the value we will display.
-        self.rawvalue = 0
-
-        self.SetBackgroundColour('light blue')
-        self.SetForegroundColour('orange')
-
-        # Capture paint events for purpose of updating
-        # the displayed value.
-        self.Bind(wx.EVT_PAINT, self.onPaint)
-
-    def Update(self, value, rawvalue):
-        # Updates the gauge itself, sets the raw value for
-        # the next EVT_PAINT
-        self.SetValue(value)
-        self.rawvalue = rawvalue
-
-    def onPaint(self, evt):
-        # Must always create a PaintDC when capturing
-        # an EVT_PAINT event
-        self.ShowValue(wx.PaintDC(self), evt)
-
-    def ShowValue(self, dc, evt):
-        # This method handles actual painting of and drawing
-        # on the gauge.
-
-        # Clear out the gauge
-        dc.Clear()
-        # and then carry out business as usual
-        wx.Gauge.OnPaint(self, evt)
-
-        # This is the size available to us.
-        w, h = dc.GetSize()
-
-        # This is what we will overlay on the gauge.
-        # It reflects the actual value received from the
-        # wx.Joystick.
-        txt = str(self.rawvalue)
-
-        # Copy the default font, make it bold.
-        fn = wx.Font(
-                self.GetFont().GetPointSize(),
-                self.GetFont().GetFamily(),
-                self.GetFont().GetStyle(),
-                wx.BOLD
-                )
-
-        # Set the font for the DC ...
-        dc.SetFont(fn)
-        # ... and calculate how much space our value
-        # will take up.
-        fw, fh = dc.GetTextExtent(txt)
-
-        # Calc the center of the gauge, and from that
-        # derive the origin of our value.
-        center = w / 2
-        tx = center - (fw/2)
-
-        center = h / 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.BLACK)
-        dc.DrawText(txt, tx, ty)
-
-        dc.SetTextForeground('white')
-        dc.DrawText(txt, tx-1, ty-1)
-
-
-#----------------------------------------------------------------------------
-
-class Axis(wx.Panel):
-    #
-    # This class is a container for the min, max, and current
-    # values of the joystick axis in question. It contains
-    # also special features to render a 'dummy' if the axis
-    # in question is not available.
-    #
-    def __init__(self, parent, token, stick):
-
-        self.stick = stick
-
-        #
-        # token represents the type of axis we're displaying.
-        #
-        self.token = token
-
-        #
-        # Create a call to the 'Has*()' method for the stick.
-        # X and Y are always there, so we tie the Has* method
-        # to a hardwired True value.
-        #
-        if token not in ['X', 'Y']:
-            self.HasFunc = eval('stick.Has%s' % token)
-        else:
-            self.HasFunc = self.alwaysTrue
-
-        # Now init the panel.
-        wx.Panel.__init__(self, parent, -1)
-
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-
-        if self.HasFunc():
-            #
-            # Tie our calibration functions to the appropriate
-            # stick method. If we don't have the axis in question,
-            # we won't need them.
-            #
-            self.GetMin = eval('stick.Get%sMin' % token)
-            self.GetMax = eval('stick.Get%sMax' % token)
-
-            # Create our displays and set them up.
-            self.Min = wx.StaticText(self, -1, str(self.GetMin()), style=wx.ALIGN_RIGHT)
-            self.Max = wx.StaticText(self, -1, str(self.GetMax()), style=wx.ALIGN_LEFT)
-            self.bar = AxisBar(self)
-
-            sizer.Add(self.Min, 0, wx.ALL | wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL, 1)
-            sizer.Add(self.bar, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 1)
-            sizer.Add(self.Max, 0, wx.ALL | wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL, 1)
-
-        else:
-            # We go here if the axis in question is not available.
-            self.control = wx.StaticText(self, -1, '       *** Not Present ***')
-            sizer.Add(self.control, 1, wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 1)
-
-        #----------------------------------------------------------------------------
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-        wx.CallAfter(self.Update)
-
-
-    def Calibrate(self):
-        if not self.HasFunc():
-            return
-
-        self.Min.SetLabel(str(self.GetMin()))
-        self.Max.SetLabel(str(self.GetMax()))
-
-
-    def Update(self):
-        # Don't bother if the axis doesn't exist.
-        if not self.HasFunc():
-            return
-
-        min = int(self.Min.GetLabel())
-        max = int(self.Max.GetLabel())
-
-        #
-        # Not all values are available from a wx.JoystickEvent, so I've elected
-        # to not use it at all. Therefore, we are getting our values direct from
-        # the stick. These values also seem to be more stable and reliable than
-        # those received from the event itself, so maybe it's a good idea to
-        # use the stick directly for your program.
-        #
-        # Here we either select the appropriate member of stick.GetPosition() or
-        # apply the appropriate Get*Position method call.
-        #
-        if self.token == 'X':
-            val = self.stick.GetPosition().x
-        elif self.token == 'Y':
-            val = self.stick.GetPosition().y
-        else:
-            val = eval('self.stick.Get%sPosition()' % self.token)
-
-
-        #
-        # While we might be able to rely on a range of 0-FFFFFF on Win, that might
-        # not be true of all drivers on all platforms. Thus, calc the actual full
-        # range first.
-        #
-        if min < 0:
-            max += abs(min)
-            val += abs(min)
-            min = 0        
-        range = float(max - min)
-        
-        #
-        # The relative value is used by the derived wx.Gauge since it is a
-        # positive-only control.
-        #
-        relative = 0
-        if range:
-            relative = int( val / range * 1000)
-
-        #
-        # Pass both the raw and relative values to the derived Gauge
-        #
-        self.bar.Update(relative, val)
-
-
-    def alwaysTrue(self):
-        # a dummy method used for X and Y axis.
-        return True
-
-
-#----------------------------------------------------------------------------
-
-class AxisPanel(wx.Panel):
-    #
-    # Contained herein is a panel that offers a graphical display
-    # of the levels for all axes supported by wx.Joystick. If
-    # your system doesn't have a particular axis, it will be
-    # 'dummied' for transparent use.
-    #
-    def __init__(self, parent, stick):
-
-        self.stick = stick
-
-        # Defines labels and 'tokens' to identify each
-        # supporte axis.
-        axesList = [
-            ('X Axis ', 'X'),   ('Y Axis ', 'Y'),
-            ('Z Axis ', 'Z'),   ('Rudder ', 'Rudder'),
-            ('U Axis ', 'U'),   ('V Axis ', 'V')
-            ]
-
-        # Contains a list of all axis initialized.
-        self.axes = []
-
-        wx.Panel.__init__(self, parent, -1)
-
-        sizer = wx.FlexGridSizer(3, 4, 1, 1)
-        sizer.AddGrowableCol(1)
-        sizer.AddGrowableCol(3)
-
-        #----------------------------------------------------------------------------
-
-        # Go through the list of labels and tokens and add a label and
-        # axis display to the sizer for each.
-        for label, token in axesList:
-            sizer.Add(Label(self, label), 0, wx.ALL | wx.ALIGN_RIGHT, 2)
-            t = Axis(self, token, self.stick)
-            self.axes.append(t)
-            sizer.Add(t, 1, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2)
-
-        #----------------------------------------------------------------------------
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-        wx.CallAfter(self.Update)
-
-    def Calibrate(self):
-        for i in self.axes:
-            i.Calibrate()
-
-    def Update(self):
-        for i in self.axes:
-            i.Update()
-
-
-#----------------------------------------------------------------------------
-
-class JoystickDemoPanel(wx.Panel):
-
-    def __init__(self, parent, log):
-
-        self.log = log
-
-        wx.Panel.__init__(self, parent, -1)
-
-        # Try to grab the control. If we get it, capture the stick.
-        # Otherwise, throw up an exception message and play stupid.
-        try:
-            self.stick = wx.Joystick()
-            self.stick.SetCapture(self)
-            # Calibrate our controls
-            wx.CallAfter(self.Calibrate)
-            wx.CallAfter(self.OnJoystick)
-        except NotImplementedError, v:
-            wx.MessageBox(str(v), "Exception Message")
-            self.stick = None
-
-        # One Sizer to Rule Them All...
-        sizer = wx.GridBagSizer(2,2)
-
-        self.info = InfoPanel(self, self.stick)
-        sizer.Add(self.info, (0, 0), (1, 3), wx.ALL | wx.GROW, 2)
-
-        self.info.Bind(wx.EVT_BUTTON, self.Calibrate)
-
-        self.joy = JoyPanel(self, self.stick)
-        sizer.Add(self.joy, (1, 0), (1, 1), wx.ALL | wx.GROW, 2)
-                  
-        self.pov = POVPanel(self, self.stick)
-        sizer.Add(self.pov, (1, 1), (1, 2), wx.ALL | wx.GROW, 2)
-        
-        self.axes = AxisPanel(self, self.stick)
-        sizer.Add(self.axes, (2, 0), (1, 3), wx.ALL | wx.GROW, 2)
-
-        self.buttons = JoyButtons(self, self.stick)
-        sizer.Add(self.buttons, (3, 0), (1, 3), wx.ALL | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL, 1)
-
-        self.SetSizer(sizer)
-        sizer.Fit(self)
-
-        # Capture Joystick events (if they happen)
-        self.Bind(wx.EVT_JOYSTICK_EVENTS, self.OnJoystick)
-        self.stick.SetMovementThreshold(10)
-
-
-    def Calibrate(self, evt=None):
-        # Do not try this without a stick
-        if not self.stick:
-            return
-
-        self.info.Calibrate()
-        self.axes.Calibrate()
-        self.pov.Calibrate()
-        self.buttons.Calibrate()
-
-
-    def OnJoystick(self, evt=None):
-        if not self.stick:
-            return
-
-        self.axes.Update()
-        self.joy.Update()
-        self.pov.Update()
-        if evt is not None and evt.IsButton():
-            self.buttons.Update()
-
-
-    def ShutdownDemo(self):
-        if self.stick:
-            self.stick.ReleaseCapture()
-        self.stick = None
-        
-#----------------------------------------------------------------------------
-
-def runTest(frame, nb, log):
-    if haveJoystick:
-        win = JoystickDemoPanel(nb, log)
-        return win
-    else:
-        from Main import MessagePanel
-        win = MessagePanel(nb, 'wx.Joystick is not available on this platform.',
-                           'Sorry', wx.ICON_WARNING)
-        return win
-    
-
-#----------------------------------------------------------------------------
-
-overview = """\
-<html>
-<body>
-<h1>wx.Joystick</h1>
-This demo illustrates the use of the wx.Joystick class, which is an interface to
-one or more joysticks attached to your system.
-
-<p>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 <b>can</b> get from the wx.Joystick control.
-
-<ul>
-<li>Static information such as Manufacturer ID and model name,
-<li>Analog input from up to six axes, including X and Y for the actual stick,
-<li>Button input from the fire button and any other buttons that the stick has,
-<li>and the POV control (a kind of mini-joystick on top of the joystick) that many sticks come with.
-</ul>
-
-<p>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.
-
-<h2>Data types</h2>
-
-Data from the joystick comes in two flavors: that which defines the boundaries, and that
-which defines the current state of the stick. Thus, we have Get*Max() and Get*Min() 
-methods for all axes, the max number of axes, the max number of buttons, and so on. In
-general, this data can be read once and stored to speed computation up.
-
-<h3>Analog Input</h3>
-
-Analog input (the axes) is delivered as a whole, positive number. If you need to know 
-if the axis is at zero (centered) or not, you will first have to calculate that center
-based on the max and min values. The demo shows a bar graph for each axis expressed
-in native numerical format, plus a 'centered' X-Y axis compass showing the relationship
-of that input to the calculated stick position.
-
-Analog input may be jumpy and spurious, so the control has a means of 'smoothing' the
-analog data by setting a movement threshold. This demo sets the threshold to 10, but
-you can set it at any valid value between the min and max.
-
-<h3>Button Input</h3>
-
-Button state is retrieved as one int that contains each button state mapped to a bit.
-You get the state of a button by AND-ing its bit against the returned value, in the form
-
-<pre>
-     # assume buttonState is what the stick returned, and buttonBit 
-     # is the bit you want to examine
-     
-     if (buttonState & ( 1 &lt;&lt; buttonBit )) :
-         # button pressed, do something with it
-</pre>
-
-<p>The problem here is that some OSs return a 32-bit value for up to 32 buttons 
-(imagine <i>that</i> stick!). Python V2.3 will generate an exception for bit 
-values over 30. For that reason, this demo is limited to 16 buttons.
-
-<p>Note that more than one button can be pressed at a time, so be sure to check all of them!
-     
-
-<h3>POV Input</h3>
-
-POV hats come in two flavors: four-way, and continuous. four-way POVs are restricted to
-the cardinal points of the compass; continuous, or CTS POV hats can deliver input in
-.01 degree increments, theoreticaly. The data is returned as a whole number; the last
-two digits are considered to be to the right of the decimal point, so in order to 
-use this information, you need to divide by 100 right off the bat. 
-
-<p>Different methods are provided to retrieve the POV data for a CTS hat 
-versus a four-way hat.
-
-<h2>Caveats</h2>
-
-The wx.Joystick control is in many ways incomplete at the C++ library level, but it is
-not insurmountable.  In short, while the joystick interface <i>can</i> be event-driven,
-the wx.JoystickEvent class lacks event binders for all event types. Thus, you cannot
-rely on wx.JoystickEvents to tell you when something has changed, necessarilly.
-
-<ul>
-<li>There are no events associated with the POV control.
-<li>There are no events associated with the Rudder
-<li>There are no events associated with the U and V axes.
-</ul>
-
-<p>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. 
-
-<p>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().
-
-</body>
-</html>
-"""
-
-#----------------------------------------------------------------------------
-
-if __name__ == '__main__':
-    import sys,os
-    import run
-    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])