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
86
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 ' '.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
139
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
148 wikiutil.send_title(request, self.page.split_title(request, force=1),
149 print_mode=1, media='projection')
150
151
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()