# Module `Gnumed.wxpython.gmSnellen`

GNUmed onscreen Snellen Chart emulator.

FIXME: store screen size

## Classes

`class cSnellenCfgDlg`
  Expand source code

      class cSnellenCfgDlg (wx.Dialog):
              """
              Dialogue class to get Snellen chart settings.
              """
              def __init__ (self):
                      wx.Dialog.__init__(
                              self,
                              None,
                              -1,
                              _("Snellen Chart Setup"),
                              wx.DefaultPosition,
                              wx.Size(350, 200)
                      )

      #               print wx.DisplaySize()
      #               print wx.DisplaySizeMM()

                      vbox = wx.BoxSizer (wx.VERTICAL)
                      hbox1 = wx.BoxSizer (wx.HORIZONTAL)
                      hbox1.Add (wx.StaticText(self, -1, _("Screen Height (cm): ")), 0, wx.ALL, 15)
                      self.height_ctrl = wx.SpinCtrl (self, -1, value = "25", min = 10, max = 100)
                      hbox1.Add (self.height_ctrl, 1, wx.TOP, 15)
                      vbox.Add (hbox1, 1, wx.EXPAND)
                      hbox2 = wx.BoxSizer (wx.HORIZONTAL)
                      hbox2.Add (wx.StaticText(self, -1, _("Screen Width (cm): ")), 0, wx.ALL, 15)
                      self.width_ctrl = wx.SpinCtrl (self, -1, value = "30", min = 10, max = 100)
                      hbox2.Add (self.width_ctrl, 1, wx.TOP, 15)
                      vbox.Add (hbox2, 1, wx.EXPAND)
                      hbox3 = wx.BoxSizer (wx.HORIZONTAL)
                      hbox3.Add (wx.StaticText(self, -1, _("Alphabet: ")), 0, wx.ALL, 15)
                      self.alpha_ctrl = wx.Choice (self, -1, choices = cSnellenChart.alphabets.keys ())
                      hbox3.Add (self.alpha_ctrl, 1, wx.TOP, 15)
                      vbox.Add (hbox3, 1, wx.EXPAND)
                      self.mirror_ctrl = wx.CheckBox (self, -1, label = _("Mirror"))
                      vbox.Add (self.mirror_ctrl, 0, wx.ALL, 15)
                      vbox.Add (wx.StaticText (self, -1,
      _("""Control Snellen chart using mouse:
      left-click increases text
      right-click decreases text
      double-click ends""")), 0, wx.ALL, 15)
                      hbox5 = wx.BoxSizer (wx.HORIZONTAL)
                      ok = wx.Button(self, wx.ID_OK, _(" OK "), size=wx.DefaultSize)
                      cancel = wx.Button (self, wx.ID_CANCEL, _(" Cancel "),
                                                         size=wx.DefaultSize)
                      hbox5.Add (ok, 1, wx.TOP, 15)
                      hbox5.Add (cancel, 1, wx.TOP, 15)
                      vbox.Add (hbox5, 1, wx.EXPAND)
                      self.SetSizer (vbox)
                      self.SetAutoLayout (1)
                      vbox.Fit (self)

                      wx.EVT_BUTTON (ok, wx.ID_OK, self.OnOK)
                      wx.EVT_BUTTON (cancel, wx.ID_CANCEL, self.OnCancel)
                      wx.EVT_CLOSE (self, self.OnClose )
      #               self.Show(1)
      #               self.parent = parent

              def OnClose (self, event):
                      self.EndModal (wx.ID_CANCEL)

              def OnCancel (self, event):
                      self.EndModal (wx.ID_CANCEL)

              def OnOK (self, event):
      #               if self.Validate() and self.TransferDataFromWindow():
                      selected_alpha_string = self.alpha_ctrl.GetStringSelection()
                      if selected_alpha_string is None or len (selected_alpha_string) < 2:
                              alpha = cSnellenChart.latin
                      else:
                              alpha = cSnellenChart.alphabets[selected_alpha_string]
                      height = self.height_ctrl.GetValue ()
                      width = self.width_ctrl.GetValue ()
                      mirr = self.mirror_ctrl.GetValue()
                      self.vals = (width, height, alpha, mirr)
                      self.EndModal(wx.ID_OK)

  Dialogue class to get Snellen chart settings.

  ### Ancestors

  - wx._core.Dialog
  - wx._core.TopLevelWindow
  - wx._core.NonOwnedWindow
  - wx._core.Window
  - wx._core.WindowBase
  - wx._core.EvtHandler
  - wx._core.Object
  - wx._core.Trackable
  - sip.wrapper
  - sip.simplewrapper

  ### Methods

  `def OnCancel(self, event)`
    Expand source code

        def OnCancel (self, event):
                self.EndModal (wx.ID_CANCEL)

  `def OnClose(self, event)`
    Expand source code

        def OnClose (self, event):
                self.EndModal (wx.ID_CANCEL)

  `def OnOK(self, event)`
    Expand source code

                def OnOK (self, event):
        #               if self.Validate() and self.TransferDataFromWindow():
                        selected_alpha_string = self.alpha_ctrl.GetStringSelection()
                        if selected_alpha_string is None or len (selected_alpha_string) < 2:
                                alpha = cSnellenChart.latin
                        else:
                                alpha = cSnellenChart.alphabets[selected_alpha_string]
                        height = self.height_ctrl.GetValue ()
                        width = self.width_ctrl.GetValue ()
                        mirr = self.mirror_ctrl.GetValue()
                        self.vals = (width, height, alpha, mirr)
                        self.EndModal(wx.ID_OK)

`class cSnellenChart (width,
height,
alpha=[<function cSnellenChart.O>, <function cSnellenChart.cross>, <function cSnellenChart.star>, <function cSnellenChart.box>],
mirr=0,
parent=None)`
  Expand source code

      class cSnellenChart(wx.Frame):

              def convert (self, X,Y):
                      """Converts a pair of co-ordinates from block co-ords to real.

                      X, Y    -- define top-left corner of current character
                      """
                      if self.mirror:
                              X = 5-X
                      return wx.Point(
                              int ((X * self.blockX) + self.startX),
                              int ((Y * self.blockY) + self.startY)
                      )

              def O (self):
                      """
                      Draws the letter O
                      """
                      self._draw_arc (2.5, 2.5, 2.5, 0, 360)

              def Q (self):
                      self.O()
                      self._draw_line (2.6, 3, 4, 5)

              def C (self):
                      if self.mirror:
                              self._draw_arc (2.5, 2.5, 2.5, 140, -140)
                      else:
                              self._draw_arc (2.5, 2.5, 2.5, 40, 320)

              def G (self):
                      if self.mirror:
                              self._draw_arc (2.5, 2.5, 2.5, 140, -150)
                      else:
                              self._draw_arc (2.5, 2.5, 2.5, 40, 330)
                      self._draw_rect (2.5, 2.7, 5, 3.7)
                      self._draw_rect (4, 2.7, 5, 5)

              def W (self):
                      self._draw_line (0, 0, 1, 5)
                      self._draw_line (2, 0, 1, 5)
                      self._draw_line (2, 0, 3, 5)
                      self._draw_line (4, 0, 3, 5)

              def V (self):
                      self._draw_line (0, 0, 2, 5)
                      self._draw_line (4, 0, 2, 5)

              def T (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (2, 1, 3, 5)

              def I (self):
                      self._draw_rect (2, 0, 3, 5)

              def A (self):
                      self._draw_line (2, 0, 0, 5)
                      self._draw_line (2, 0, 4, 5)
                      self._draw_rect (1.4, 2.5, 3.6, 3.5)

              def F (self):
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (1, 0, 5, 1)
                      self._draw_rect (1, 2, 5, 3)

              def E (self):
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 2, 5, 3)
                      self._draw_rect (0, 4, 5, 5)

              def BackE (self):
                      self._draw_rect (4, 0, 5, 5)
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 2, 5, 3)
                      self._draw_rect (0, 4, 5, 5)

              def UpE (self):
                      self._draw_rect (0, 4, 5, 5)
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (2, 0, 3, 5)
                      self._draw_rect (4, 0, 5, 5)

              def DownE (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (2, 0, 3, 5)
                      self._draw_rect (4, 0, 5, 5)

              def H (self):
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (4, 0, 5, 5)
                      self._draw_rect (1, 2, 4, 3)

              def K (self):
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_line (3.5, 0, 0.5, 2.5, width = 1.5)
                      self._draw_line (0.5, 2.5, 3.5, 5, width = 1.5)

              def L (self):
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (1, 4, 5, 5)

              def Z (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 4, 5, 5)
                      self._draw_line (3.5, 1, 0, 4, width = 1.5)

              def X (self):
                      self._draw_line (4, 0, 0, 5)
                      self._draw_line (0, 0, 4, 5)

              def NM (self):
                      """Sidebars common to N and M
                      """
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (4, 0, 5, 5)

              def N (self):
                      self.NM ()
                      self._draw_line (0, 0, 4, 5)

              def BackN (self):
                      self.NM ()
                      self._draw_line (4, 0, 0, 5)

              def M (self):
                      self.NM ()
                      self._draw_line (0, 0, 2, 5)
                      self._draw_line (4, 0, 2, 5)

              def gamma (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 0, 1, 5)

              def delta (self):
                      self._draw_line (2, 0, 0, 5)
                      self._draw_line (2, 0, 4, 5)
                      self._draw_rect (0.5, 4, 4.5, 5)

              def pi (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 0, 1, 5)
                      self._draw_rect (4, 0, 5, 5)

              def cross (self):
                      self._draw_rect (2, 0, 3, 5)
                      self._draw_rect (0, 2, 5, 3)

              def box (self):
                      self._draw_rect (0, 0, 5, 1)
                      self._draw_rect (0, 4, 5, 5)
                      self._draw_rect (0, 1, 1, 4)
                      self._draw_rect (4, 1, 5, 4)

              def star (self):
                      """
                      Star of 5 points
                      """
                      n = 5 # can change here
                      list = []
                      for i in range (0, n):
                              theta = (i+0.00001)/n*2*math.pi # points on a circle inside the 5x5 grid
                              x = 2.5 + 2.5*math.sin (theta)
                              y = 2.5 - 2.5*math.cos (theta)
                              list.append (self.convert (x, y)) # add point to list
                              theta = (i+0.5)/n*2*math.pi
                              x = 2.5 + math.sin (theta)
                              y = 2.5 - math.cos (theta)
                              list.append (self.convert (x, y))
                      self.dc.DrawPolygon (list, fill_style = wx.WINDING_RULE)

              latin = [A, C,
                               C, E, F, G,
                               H, I, K, L, M,
                               N, O, Q, T, V,
                               W, X, Z]

              fourE = [E, UpE, DownE, BackE]

              greek = [A, gamma, delta, E,
                               Z, H, I, K, M,
                               N, O, pi, T, X]

              cyrillic = [A, delta, E, BackN,
                                 K, M, H, O, pi,
                                 T, C, X]

              symbol = [O, cross, star, box]

              alphabets = {
                      _("Latin"): latin,
                      _("Greek"): greek,
                      _("Cyrillic"): cyrillic,
                      _("Four Es"): fourE,
                      _("Symbol"): symbol
              }

              def __init__(self, width, height, alpha = symbol, mirr = 0, parent = None):
                      """
                      Initialise. width and height define the physical size of the
                      CRT in cm.
                      """
                      wx.Frame.__init__ (self, parent, -1, _("Snellen Chart"))

                      # width/Y is screen size (X/Y in cm)
                      #wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
      #               screensizes = {_("14 inch"):(28, 21), _("16 inch"):(30, 23)}
                      self.screen_width_cm = width
                      self.screen_height_cm = height

                      self.screen_width_pixel = 0
                      self.screen_height_pixel = 0

                      self.standard_patient_chart_distances = [3, 5, 6, 7.5, 9, 12, 15, 18, 24, 30, 48, 60] # in metres
                      self.mirror = mirr
                      self.alphabet = alpha

                      wx.EVT_CLOSE (self, self.OnClose)
                      wx.EVT_KEY_DOWN (self, self.OnKeyUp)
                      wx.EVT_LEFT_UP (self, self.OnLeftDown)
                      wx.EVT_RIGHT_UP (self, self.OnRightDown)
                      wx.EVT_LEFT_DCLICK (self, self.OnDClick)
                      wx.EVT_PAINT (self, self.OnPaint)
      #               wx.EVT_WINDOW_CREATE (self, self.OnCreate)

                      self.ShowFullScreen(1)
              #---------------------------------
              # event handlers
              #---------------------------------
      #       def OnCreate(self, event):
      #               self.ShowFullScreen(1)
              #---------------------------------
              def OnPaint (self, event):
                      self.dc = wx.PaintDC(self)
                      if self.screen_width_pixel == 0:
                              self.screen_width_pixel, self.screen_height_pixel = self.GetClientSize()
                              self.set_distance(2)
      #                       _log.info('I think the screen size is %d x %d' % (self.screen_width_pixel, self.screen_height_pixel))

      #               self.setup_DC()
                      self.dc.SetFont(wx.Font (36, wx.ROMAN, wx.NORMAL, wx.NORMAL))
                      self.dc.SetBrush(wx.BLACK_BRUSH)
                      self.dc.SetBackground(wx.WHITE_BRUSH)
                      self.dc.SetPen(wx.TRANSPARENT_PEN)

      #               self.draw ()
                      # clear the screen
                      self._swap_fg_bg_col()
                      self.dc.DrawRectangle(0, 0, self.screen_width_pixel, self.screen_height_pixel)
                      self._swap_fg_bg_col ()
                      # draw size
                      self.dc.DrawText (str(self.standard_patient_chart_distances[self.distance]), 20, 20)
                      self.startX = self.spacing
                      for i in self.choices:
                              i (self)
                              self.startX += self.blockX*5
                              self.startX += self.spacing

                      self.dc = None

              def OnKeyUp (self, key):
                      if key.GetKeyCode() == wx.WXK_UP and self.distance < len (self.standard_patient_chart_distances)-1:
                              self.set_distance (self.distance+1)
                      if key.GetKeyCode() == wx.WXK_DOWN and self.distance > 0:
                              self.set_distance (self.distance-1)
                      if key.GetKeyCode() == wx.WXK_ESCAPE:
                              self.Destroy ()

              def OnLeftDown (self, key):
                      if self.distance > 0:
                              self.set_distance (self.distance-1)
                      self.Refresh ()

              def OnRightDown (self, key):
                      if self.distance < len(self.standard_patient_chart_distances)-1:
                              self.set_distance (self.distance+1)
                      self.Refresh()

              def OnDClick (self, key):
                      self.DestroyLater()

              def OnClose (self, event):
                      self.DestroyLater()

              def DestroyWhenApp (self):
                      import sys
                      sys.exit (0)

              #---------------------------------
              # internal API
              #---------------------------------
              def _swap_fg_bg_col(self):
                      """Swap fore- and background pens."""
                      background = self.dc.GetBackground()
                      foreground = self.dc.GetBrush()
                      self.dc.SetBrush(background)
                      self.dc.SetBackground(foreground)
              #---------------------------------
              def _draw_rect(self, x1, y1, x2, y2):
                      """Draw a rectangle."""
                      x1, y1 = self.convert (x1, y1)
                      x2, y2 = self.convert (x2, y2)

                      width = x2 - x1
                      if width < 0:
                              width = -width
                              x = x2
                      else:
                              x = x1

                      height = y2 - y1
                      if height < 0:
                              height = -height
                              y = y2
                      else:
                              y = y1

                      self.dc.DrawRectangle(x, y, width, height)
              #---------------------------------
              def _draw_arc (self, x, y, arm, start, end):
                      """
                      Draws an arc-stroke, 1 unit wide, subtending (x, y), the outer
                      distance is arm, between start and end angle
                      """
                      topx, topy = self.convert (x-arm, y-arm)
                      botx, boty = self.convert (x+arm, y+arm)
                      width = botx - topx
                      if width < 0:
                              width = -width
                              t = botx
                              botx = topx
                              topx = t
                      height = boty - topy
                      self.dc.DrawEllipticArc(topx, topy, width, height, start, end)
                      # now do wedge as background, to give arc pen-stroke
                      arm -= 1
                      self._swap_fg_bg_col()
                      topx, topy = self.convert (x-arm, y-arm)
                      botx, boty = self.convert (x+arm, y+arm)
                      width = botx - topx
                      if width < 0:
                              width = -width
                              t = botx
                              botx = topx
                              topx = t
                      height = boty- topy
                      self.dc.DrawEllipticArc(topx, topy, width, height, start, end)
                      self._swap_fg_bg_col()
              #---------------------------------
              def _draw_line(self, x1, y1, x2, y2, width = 1):
                      """Draws straight descending letter-stroke.

                      (x1, y1) is top-left,
                      (x2, y2) is bottom left point
                      """
                      coords = [
                              self.convert (x1, y1),
                              self.convert (x1+width, y1),
                              self.convert (x2+width, y2),
                              self.convert (x2, y2)
                      ]
                      self.dc.DrawPolygon(coords)
              #---------------------------------
              #---------------------------------
              def set_distance (self, n):
                      """
                      Sets standard viewing distance, against which patient is
                      compared. n is an index to the list self.standard_patient_chart_distances
                      """
                      self.distance = n
                      # Snellen characters are the smallest readable characters by
                      # an average person at the stated distance. They are defined
                      # exactly as being in a box which subtends 5' of an arc on the
                      # patient's eye, each stroke subtending 1' of arc
                      one_minute = (math.pi / 180) / 60
                      blocksize = (self.standard_patient_chart_distances[n] * 100) * math.atan(one_minute) # in cm
                      # convert to pixels
                      self.blockX = int (blocksize / self.screen_width_cm * self.screen_width_pixel)
                      self.blockY = int (blocksize / self.screen_height_cm * self.screen_height_pixel)
                      # how many characters can we fit now?
                      chars = int (self.screen_width_pixel / (self.blockX*5)) - 1
                      if chars < 1:
                              chars = 1
                      if chars > 7:
                              chars = 7
                      if chars < len (self.alphabet):
                              self.choices = []
                              while len (self.choices) < chars:
                                      c = random.choice (self.alphabet)
                                      if not c in self.choices:
                                              self.choices.append (c)
                      else:
                              self.choices = [ random.choice(self.alphabet) for i in range(1, chars) ]
                      self.spacing = int ((self.screen_width_pixel -
                      (chars*self.blockX*5))/(chars+1))
                      if self.spacing < 0:
                              self.spacing = 0
                      self.startY = int ((self.screen_height_pixel-(self.blockY*5))/2)

  Frame() Frame(parent, id=ID_ANY, title=EmptyString, pos=DefaultPosition, size=DefaultSize, style=DEFAULT_FRAME_STYLE, name=FrameNameStr)

  A frame is a window whose size and position can (usually) be changed by the user.

  Initialise. width and height define the physical size of the CRT in cm.

  ### Ancestors

  - wx._core.Frame
  - wx._core.TopLevelWindow
  - wx._core.NonOwnedWindow
  - wx._core.Window
  - wx._core.WindowBase
  - wx._core.EvtHandler
  - wx._core.Object
  - wx._core.Trackable
  - sip.wrapper
  - sip.simplewrapper

  ### Class variables

  `var alphabets`
  `var cyrillic`
  `var fourE`
  `var greek`
  `var latin`
  `var symbol`

  ### Methods

  `def A(self)`
    Expand source code

        def A (self):
                self._draw_line (2, 0, 0, 5)
                self._draw_line (2, 0, 4, 5)
                self._draw_rect (1.4, 2.5, 3.6, 3.5)

  `def BackE(self)`
    Expand source code

        def BackE (self):
                self._draw_rect (4, 0, 5, 5)
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 2, 5, 3)
                self._draw_rect (0, 4, 5, 5)

  `def BackN(self)`
    Expand source code

        def BackN (self):
                self.NM ()
                self._draw_line (4, 0, 0, 5)

  `def C(self)`
    Expand source code

        def C (self):
                if self.mirror:
                        self._draw_arc (2.5, 2.5, 2.5, 140, -140)
                else:
                        self._draw_arc (2.5, 2.5, 2.5, 40, 320)

  `def DestroyWhenApp(self)`
    Expand source code

        def DestroyWhenApp (self):
                import sys
                sys.exit (0)

  `def DownE(self)`
    Expand source code

        def DownE (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (2, 0, 3, 5)
                self._draw_rect (4, 0, 5, 5)

  `def E(self)`
    Expand source code

        def E (self):
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 2, 5, 3)
                self._draw_rect (0, 4, 5, 5)

  `def F(self)`
    Expand source code

        def F (self):
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (1, 0, 5, 1)
                self._draw_rect (1, 2, 5, 3)

  `def G(self)`
    Expand source code

        def G (self):
                if self.mirror:
                        self._draw_arc (2.5, 2.5, 2.5, 140, -150)
                else:
                        self._draw_arc (2.5, 2.5, 2.5, 40, 330)
                self._draw_rect (2.5, 2.7, 5, 3.7)
                self._draw_rect (4, 2.7, 5, 5)

  `def H(self)`
    Expand source code

        def H (self):
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (4, 0, 5, 5)
                self._draw_rect (1, 2, 4, 3)

  `def I(self)`
    Expand source code

        def I (self):
                self._draw_rect (2, 0, 3, 5)

  `def K(self)`
    Expand source code

        def K (self):
                self._draw_rect (0, 0, 1, 5)
                self._draw_line (3.5, 0, 0.5, 2.5, width = 1.5)
                self._draw_line (0.5, 2.5, 3.5, 5, width = 1.5)

  `def L(self)`
    Expand source code

        def L (self):
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (1, 4, 5, 5)

  `def M(self)`
    Expand source code

        def M (self):
                self.NM ()
                self._draw_line (0, 0, 2, 5)
                self._draw_line (4, 0, 2, 5)

  `def N(self)`
    Expand source code

        def N (self):
                self.NM ()
                self._draw_line (0, 0, 4, 5)

  `def NM(self)`
    Expand source code

        def NM (self):
                """Sidebars common to N and M
                """
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (4, 0, 5, 5)

    Sidebars common to N and M

  `def O(self)`
    Expand source code

        def O (self):
                """
                Draws the letter O
                """
                self._draw_arc (2.5, 2.5, 2.5, 0, 360)

    Draws the letter O

  `def OnClose(self, event)`
    Expand source code

        def OnClose (self, event):
                self.DestroyLater()

  `def OnDClick(self, key)`
    Expand source code

        def OnDClick (self, key):
                self.DestroyLater()

  `def OnKeyUp(self, key)`
    Expand source code

        def OnKeyUp (self, key):
                if key.GetKeyCode() == wx.WXK_UP and self.distance < len (self.standard_patient_chart_distances)-1:
                        self.set_distance (self.distance+1)
                if key.GetKeyCode() == wx.WXK_DOWN and self.distance > 0:
                        self.set_distance (self.distance-1)
                if key.GetKeyCode() == wx.WXK_ESCAPE:
                        self.Destroy ()

  `def OnLeftDown(self, key)`
    Expand source code

        def OnLeftDown (self, key):
                if self.distance > 0:
                        self.set_distance (self.distance-1)
                self.Refresh ()

  `def OnPaint(self, event)`
    Expand source code

                def OnPaint (self, event):
                        self.dc = wx.PaintDC(self)
                        if self.screen_width_pixel == 0:
                                self.screen_width_pixel, self.screen_height_pixel = self.GetClientSize()
                                self.set_distance(2)
        #                       _log.info('I think the screen size is %d x %d' % (self.screen_width_pixel, self.screen_height_pixel))

        #               self.setup_DC()
                        self.dc.SetFont(wx.Font (36, wx.ROMAN, wx.NORMAL, wx.NORMAL))
                        self.dc.SetBrush(wx.BLACK_BRUSH)
                        self.dc.SetBackground(wx.WHITE_BRUSH)
                        self.dc.SetPen(wx.TRANSPARENT_PEN)

        #               self.draw ()
                        # clear the screen
                        self._swap_fg_bg_col()
                        self.dc.DrawRectangle(0, 0, self.screen_width_pixel, self.screen_height_pixel)
                        self._swap_fg_bg_col ()
                        # draw size
                        self.dc.DrawText (str(self.standard_patient_chart_distances[self.distance]), 20, 20)
                        self.startX = self.spacing
                        for i in self.choices:
                                i (self)
                                self.startX += self.blockX*5
                                self.startX += self.spacing

                        self.dc = None

  `def OnRightDown(self, key)`
    Expand source code

        def OnRightDown (self, key):
                if self.distance < len(self.standard_patient_chart_distances)-1:
                        self.set_distance (self.distance+1)
                self.Refresh()

  `def Q(self)`
    Expand source code

        def Q (self):
                self.O()
                self._draw_line (2.6, 3, 4, 5)

  `def T(self)`
    Expand source code

        def T (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (2, 1, 3, 5)

  `def UpE(self)`
    Expand source code

        def UpE (self):
                self._draw_rect (0, 4, 5, 5)
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (2, 0, 3, 5)
                self._draw_rect (4, 0, 5, 5)

  `def V(self)`
    Expand source code

        def V (self):
                self._draw_line (0, 0, 2, 5)
                self._draw_line (4, 0, 2, 5)

  `def W(self)`
    Expand source code

        def W (self):
                self._draw_line (0, 0, 1, 5)
                self._draw_line (2, 0, 1, 5)
                self._draw_line (2, 0, 3, 5)
                self._draw_line (4, 0, 3, 5)

  `def X(self)`
    Expand source code

        def X (self):
                self._draw_line (4, 0, 0, 5)
                self._draw_line (0, 0, 4, 5)

  `def Z(self)`
    Expand source code

        def Z (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 4, 5, 5)
                self._draw_line (3.5, 1, 0, 4, width = 1.5)

  `def box(self)`
    Expand source code

        def box (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 4, 5, 5)
                self._draw_rect (0, 1, 1, 4)
                self._draw_rect (4, 1, 5, 4)

  `def convert(self, X, Y)`
    Expand source code

        def convert (self, X,Y):
                """Converts a pair of co-ordinates from block co-ords to real.

                X, Y    -- define top-left corner of current character
                """
                if self.mirror:
                        X = 5-X
                return wx.Point(
                        int ((X * self.blockX) + self.startX),
                        int ((Y * self.blockY) + self.startY)
                )

    Converts a pair of co-ordinates from block co-ords to real.

    X, Y – define top-left corner of current character

  `def cross(self)`
    Expand source code

        def cross (self):
                self._draw_rect (2, 0, 3, 5)
                self._draw_rect (0, 2, 5, 3)

  `def delta(self)`
    Expand source code

        def delta (self):
                self._draw_line (2, 0, 0, 5)
                self._draw_line (2, 0, 4, 5)
                self._draw_rect (0.5, 4, 4.5, 5)

  `def gamma(self)`
    Expand source code

        def gamma (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 0, 1, 5)

  `def pi(self)`
    Expand source code

        def pi (self):
                self._draw_rect (0, 0, 5, 1)
                self._draw_rect (0, 0, 1, 5)
                self._draw_rect (4, 0, 5, 5)

  `def set_distance(self, n)`
    Expand source code

        def set_distance (self, n):
                """
                Sets standard viewing distance, against which patient is
                compared. n is an index to the list self.standard_patient_chart_distances
                """
                self.distance = n
                # Snellen characters are the smallest readable characters by
                # an average person at the stated distance. They are defined
                # exactly as being in a box which subtends 5' of an arc on the
                # patient's eye, each stroke subtending 1' of arc
                one_minute = (math.pi / 180) / 60
                blocksize = (self.standard_patient_chart_distances[n] * 100) * math.atan(one_minute) # in cm
                # convert to pixels
                self.blockX = int (blocksize / self.screen_width_cm * self.screen_width_pixel)
                self.blockY = int (blocksize / self.screen_height_cm * self.screen_height_pixel)
                # how many characters can we fit now?
                chars = int (self.screen_width_pixel / (self.blockX*5)) - 1
                if chars < 1:
                        chars = 1
                if chars > 7:
                        chars = 7
                if chars < len (self.alphabet):
                        self.choices = []
                        while len (self.choices) < chars:
                                c = random.choice (self.alphabet)
                                if not c in self.choices:
                                        self.choices.append (c)
                else:
                        self.choices = [ random.choice(self.alphabet) for i in range(1, chars) ]
                self.spacing = int ((self.screen_width_pixel -
                (chars*self.blockX*5))/(chars+1))
                if self.spacing < 0:
                        self.spacing = 0
                self.startY = int ((self.screen_height_pixel-(self.blockY*5))/2)

    Sets standard viewing distance, against which patient is compared. n is an index to the list self.standard_patient_chart_distances

  `def star(self)`
    Expand source code

        def star (self):
                """
                Star of 5 points
                """
                n = 5 # can change here
                list = []
                for i in range (0, n):
                        theta = (i+0.00001)/n*2*math.pi # points on a circle inside the 5x5 grid
                        x = 2.5 + 2.5*math.sin (theta)
                        y = 2.5 - 2.5*math.cos (theta)
                        list.append (self.convert (x, y)) # add point to list
                        theta = (i+0.5)/n*2*math.pi
                        x = 2.5 + math.sin (theta)
                        y = 2.5 - math.cos (theta)
                        list.append (self.convert (x, y))
                self.dc.DrawPolygon (list, fill_style = wx.WINDING_RULE)

    Star of 5 points