1 """
   2     MoinMoin - slideshow action
   3 
   4     Usage - Used together with the [[Slide]] macro allows a slideshow to be
   5             defined on a single wiki page.
   6 
   7             Create a page with the format:
   8 
   9                 general introduction or comments
  10                 [[Slide]]
  11                 Slide 1 contents
  12                 [[Slide]]
  13                 Slide 2 contents
  14                 ...
  15                 [[Slide]]
  16                 Final slide contents
  17 
  18             The [[Slide]] macro creates links to the slideshow action.  The
  19             slideshow action takes a parameter 'slidenumber', which is the
  20             (1-based) number of the slide to display.  The display uses the
  21             large screen 'projection' media.
  22 
  23             This action adds two sets of navigation aids for the slides:
  24             1) some javascript, so that mouse clicks or space bar move to the next page
  25             2) a navigation footer, similar to the [[Navigation]] macro
  26 
  27     @copyright: 2005 Jim Clark
  28     @license: GNU GPL, see COPYING for details.
  29 """
  30 
  31 import re
  32 from MoinMoin import config, wikiutil
  33 from MoinMoin.Page import Page
  34 from MoinMoin.parser.wiki import Parser
  35 from MoinMoin.formatter.text_html import Formatter
  36 
  37 
  38 class slideshow:
  39     slide_pattern = re.compile(r'\[\[Slide\]\]')
  40     script_template = """
  41 <script type="text/javascript"><!--
  42 function firstSlide() {window.location="%s"}
  43 function prevSlide() {window.location="%s"}
  44 function nextSlide() {window.location="%s"}
  45 function lastSlide() {window.location="%s"}
  46 function handleKey(e) {
  47     var key;
  48     if (e == null) {key = event.keyCode} //IE
  49     else {if (e.altKey || e.ctrlKey) {return true} key = e.which} // Mozilla
  50     switch(key) {
  51         case 49: firstSlide(); break //'1'
  52         case 32: nextSlide(); break  //space
  53         case 60: prevSlide(); break  //'<'
  54         case 62: nextSlide(); break  //'>'
  55         default:
  56     }
  57 }
  58 document.onkeypress = handleKey
  59 document.onclick = nextSlide
  60 document.ondblclick = prevSlide
  61 //-->
  62 </script>"""
  63 
  64     def __init__(self, pagename, request):
  65         self.pagename = pagename
  66         try:
  67             self.slidenumber = int(request.form.get('slidenumber', [1])[0])
  68         except ValueError:
  69             self.slidenumber = 1
  70         request.formatter = Formatter(request)
  71         request.page = Page(request, pagename)
  72         request.formatter.page = request.page
  73         self.request = request
  74         self.page = self.request.page
  75         self.formatter = self.request.formatter
  76         self._parseslides()
  77         
  78     def _parseslides(self):
  79         """ Parse slide content from the base page.  The simple parser currently
  80         uses the [[Slide]] macro as the delimeter - perhaps it would be better
  81         to do this automatically based on eg H1 markers?
  82         """
  83         self.slideinfo = []
  84         startpos = 0
  85         # setup slideinfo as a list of tuples representing the start and end
  86         # characters of each slides content
  87         for match in self.slide_pattern.finditer(self.request.page.get_raw_body()):
  88             self.slideinfo.append((startpos, match.start()))
  89             startpos = match.end()
  90         if startpos:
  91             self.slideinfo.append((startpos, len(self.request.page.get_raw_body())))
  92 
  93     def slideurl(self, slidenumber):
  94         """ Return a url for a link to another slide based on this page
  95         """
  96         return "%s/%s?action=slideshow&slidenumber=%d" % \
  97                (self.request.getScriptname(), self.pagename, slidenumber)
  98 
  99     def navigationscript(self):
 100         """ Return a section of javascript for capturing mouse button and
 101         keyboard events and using for slide navigation.
 102         """
 103         urls = (self.slideurl(1),
 104                 self.slideurl(self.slidenumber - 1),
 105                 self.slideurl(self.slidenumber + 1),
 106                 self.slideurl(len(self.slideinfo) - 1))
 107         return (self.script_template % urls)
 108 
 109     def navigationtable(self):
 110         """ Return an HTML table for navigating between slides
 111         """
 112         items = []
 113         items.append(self.page.link_to(self.request, text='End'))
 114         items.append(self.page.link_to(self.request, text='Edit', querystr='action=edit'))
 115         items.append(self.page.link_to(self.request, text='|<', querystr='action=slideshow&slidenumber=%d' % 1))
 116         items.append(self.page.link_to(self.request, text='<<', querystr='action=slideshow&slidenumber=%d' % (self.slidenumber - 1)))
 117         items.append('Slide %d of %d' % (self.slidenumber, len(self.slideinfo) - 1))
 118         items.append(self.page.link_to(self.request, text='>>', querystr='action=slideshow&slidenumber=%d' % (self.slidenumber + 1)))
 119         items.append(self.page.link_to(self.request, text='>|', querystr='action=slideshow&slidenumber=%d' % (len(self.slideinfo) - 1)))
 120 
 121         return self.formatter.table(1, {'tableclass': 'navigation'}) + \
 122                self.formatter.table_row(1) + \
 123                self.formatter.table_cell(1) + \
 124                ' &nbsp; '.join(items) + \
 125                self.formatter.table_cell(0) + \
 126                self.formatter.table_row(0) + \
 127                self.formatter.table(0)
 128 
 129 
 130     def render(self):
 131         """ Render a slide from a page """
 132         request = self.request
 133         if self.slidenumber < 1 or self.slidenumber > len(self.slideinfo) - 1:
 134             request.http_headers()
 135             request.page.send_page(request, msg='End of slides') 
 136             return
 137         
 138         # Extract the requsted slide content from the page body and parse it
 139         # as a wiki page in its own right
 140         (startpos, endpos) = self.slideinfo[self.slidenumber]
 141         slide = request.page.get_raw_body()[startpos:endpos]
 142         parser = Parser(slide, request)
 143 
 144         request.http_headers()
 145         request.setContentLanguage(request.lang)
 146         
 147         # Send the header in 'projection' mode - for large print and no headings
 148         wikiutil.send_title(request, self.page.split_title(request, force=1),
 149                             print_mode=1, media='projection')
 150 
 151         # Write the extracted slide, as well as the navigation aids
 152         request.write(self.navigationscript())
 153         request.write(request.formatter.startContent("content"))
 154         parser.format(request.formatter)
 155         request.write(self.navigationtable())
 156         request.write(request.formatter.endContent())
 157         wikiutil.send_footer(request, self.pagename, print_mode=1)
 158 
 159 def execute(pagename, request):
 160     slideshow(pagename, request).render()

MoinMoin: JimClark/slideshow.py (last edited 2007-10-29 19:06:59 by localhost)