Package VisionEgg :: Module WrappedText |
[frames] | no frames]

# Source Code for Module VisionEgg.WrappedText

      1  #!/usr/bin/env python
      2  """Module containing the Multi-line text stimulus class WrappedText, as well
      3  as a simple example of its use."""
      4  # Copyright (c) 2007 Eamon Caddigan, University of Illinois
      5  # License: LGPL (see LICENSE.txt distributed with this file)
      6  # Created on 2007-11-15
      7  #
      8  # TODO: (more of a wishlist)
      9  #   * anchor parameter
     10  #   * angle parameter (I dunno, maybe you want some paragraphs tilted)
     11  #   * more robust line length calculation
     12  #   * wholesale replacement of this module with *real* formatted text (e.g.,
     13  #     ghostscript). The kerning of pygame's text is atrocious.
     14
     15  import VisionEgg.Core
     16  import VisionEgg.Text
     17  import VisionEgg.Textures
     18  import VisionEgg.ParameterTypes as ve_types
     19  import textwrap
     20
     21 -class WrappedText(VisionEgg.Core.Stimulus):
     22    """Multi-line text stimulus. No fancy formatting, but line breaks ('\\n')
     23    are preserved, and text is wrapped to fit within the stimulus
     24    boundaries."""
     25
     26    parameters_and_defaults = {
     27      'on':(True, ve_types.Boolean),
     28      'position':((0.0,0.0),
     29          ve_types.AnyOf(ve_types.Sequence2(ve_types.Real),
     30            ve_types.Sequence3(ve_types.Real),
     31            ve_types.Sequence4(ve_types.Real))),
     32      'size':(None, ve_types.Sequence2(ve_types.Real),
     33          """Defaults to the size of the screen."""),
     34      'text':('hello', ve_types.AnyOf(ve_types.String,ve_types.Unicode)),
     35      'color':((1.0,1.0,1.0),
     36          ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
     37            ve_types.Sequence4(ve_types.Real)))
     38    }
     39
     40    constant_parameters_and_defaults = {
     41      'font_name':(None, ve_types.AnyOf(ve_types.String,ve_types.Unicode),
     42          "Name of font to use. If None, use the default font"),
     43      'font_size':(30, ve_types.UnsignedInteger)
     44    }
     45
     46 -  def __init__(self, **kw):
     47      """Initialize the object, perform the initial line-splitting"""
     48      VisionEgg.Core.Stimulus.__init__(self, **kw)
     49
     50      if self.parameters.size is None:
     51        self.parameters.size = (VisionEgg.config.VISIONEGG_SCREEN_W,
     52            VisionEgg.config.VISIONEGG_SCREEN_H)
     53
     54      self._splitText()
     55
     56 -  def _splitText(self):
     57      """Split a single string into multiple lines of text, storing each as a
     58      VisionEgg.Text.Text instance"""
     59      p = self.parameters
     60      cp = self.constant_parameters
     61
     62      self._text = p.text
     63
     64      textAreaWidth = None
     65      maxLineLength = len(self._text)
     66      minLineLength = 1
     67      lineLength = maxLineLength
     68      while ((textAreaWidth > p.size[0]) or
     69          ((maxLineLength-minLineLength) > 1)) and (maxLineLength > 1):
     70        nextPosition = p.position
     71        self._textLines = []
     72
     73        try:
     74          textLineList = []
     75          for text in self._text.split("\n"):
     76            if text == "":
     77              textLineList.append("")
     78            else:
     79              textLineList.extend(textwrap.wrap(text, lineLength))
     80
     81          textAreaWidth = None
     82          for textLine in textLineList:
     83            if textLine != "":
     84              line = VisionEgg.Text.Text(text=textLine,
     85                  position = nextPosition,
     86                  anchor = "upperleft",
     87                  ignore_size_parameter = True,
     88                  color = p.color,
     89                  font_name = cp.font_name,
     90                  font_size = cp.font_size)
     91              textAreaWidth = max(textAreaWidth, line.parameters.size[0])
     92              self._textLines.append(line)
     93
     94            nextPosition = (nextPosition[0],
     95                nextPosition[1]-line.parameters.size[1])
     96
     97            # Stop adding lines if the text area's height has been reached
     98            if (p.position[1] - nextPosition[1]) > p.size[1]:
     99              break
    100
    101        except VisionEgg.Textures.TextureTooLargeError:
    102          textAreaWidth = p.size[0]+1
    103
    104        if textAreaWidth > p.size[0]:
    105          maxLineLength = lineLength
    106        else:
    107          minLineLength = lineLength
    108        lineLength = (maxLineLength+minLineLength)/2
    109
    110 -  def draw(self):
    111      """Draw the lines of text on the screen"""
    112      p = self.parameters
    113
    114      if p.on:
    115        if p.text != self._text:
    116          self._splitText()
    117
    118        for line in self._textLines:
    119          line.parameters.color = p.color
    120          line.draw()
    121
    122 -def main():
    123    """Launch VisionEgg and demo the WrappedText object"""
    124    import VisionEgg
    125    VisionEgg.start_default_logging(); VisionEgg.watch_exceptions()
    126    import VisionEgg.FlowControl
    127
    128    screen = VisionEgg.Core.get_default_screen()
    129
    130    message="""Hello.
    131
    132  This is a demonstration of the WrappedText object, which was created to allow users of VisionEgg to include large blocks of text in their programs. While this stimulus has many limitations, it should be useful for presenting on-screen instructions in experiments.
    133
    134  While you are welcome to modify this file to extend its functionality, I hope you consider sharing any such modifications with the VisionEgg community.
    135
    136  Eamon Caddigan,\nUniversity of Illinois\n15 November 2007"""
    137
    138    wt = WrappedText(text=message, position=(50,screen.size[1]-50),
    139      size=(screen.size[0]-100, screen.size[1]-100))
    140
    141    viewport = VisionEgg.Core.Viewport(screen=screen, stimuli=[wt])
    142
    143    # Frame-based presentation duration makes it easier to use pdb
    144    p = VisionEgg.FlowControl.Presentation(viewports=[viewport],
    145        go_duration=(VisionEgg.config.VISIONEGG_MONITOR_REFRESH_HZ*30,'frames'))
    146    p.go()
    147
    148    screen.close() # Called explicitly to behave better in interactive shells
    149
    150  if __name__ == "__main__":
    151    main()
    152