diff options
Diffstat (limited to 'presentty/slide.py')
-rw-r--r-- | presentty/slide.py | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/presentty/slide.py b/presentty/slide.py new file mode 100644 index 0000000..4894f45 --- /dev/null +++ b/presentty/slide.py | |||
@@ -0,0 +1,178 @@ | |||
1 | # Copyright (C) 2015 James E. Blair <corvus@gnu.org> | ||
2 | # | ||
3 | # This program is free software: you can redistribute it and/or modify | ||
4 | # it under the terms of the GNU General Public License as published by | ||
5 | # the Free Software Foundation, either version 3 of the License, or | ||
6 | # (at your option) any later version. | ||
7 | # | ||
8 | # This program is distributed in the hope that it will be useful, | ||
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | # GNU General Public License for more details. | ||
12 | # | ||
13 | # You should have received a copy of the GNU General Public License | ||
14 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | |||
16 | import urwid | ||
17 | |||
18 | class SlidePile(urwid.Pile): | ||
19 | def pack(self, size, focus=False): | ||
20 | cols = 0 | ||
21 | rows = 0 | ||
22 | for x in self.contents: | ||
23 | c,r = x[0].pack((size[0],)) | ||
24 | if c>cols: | ||
25 | cols = c | ||
26 | rows += r | ||
27 | return (cols, rows) | ||
28 | |||
29 | class SlidePadding(urwid.Padding): | ||
30 | def pack(self, size, focus=False): | ||
31 | r = self._original_widget.pack(size, focus) | ||
32 | width = max(r[0] + self.left + self.right, self.min_width) | ||
33 | width = min(size[0], width) | ||
34 | return (width, r[1]) | ||
35 | |||
36 | class SlideColumns(urwid.Columns): | ||
37 | def pack(self, size, focus=False): | ||
38 | cols = self.dividechars * (len(self.contents)-1) | ||
39 | rows = 0 | ||
40 | for widget, packing in self.contents: | ||
41 | if packing[0] == 'given': | ||
42 | allocated_cols = packing[1] | ||
43 | else: | ||
44 | allocated_cols = size[0] | ||
45 | c,r = widget.pack((allocated_cols,)) | ||
46 | if packing[0] == 'given': | ||
47 | c = allocated_cols | ||
48 | if r>rows: | ||
49 | rows = r | ||
50 | cols += c | ||
51 | return (cols, rows) | ||
52 | |||
53 | class SlideFiller(urwid.Filler): | ||
54 | pass | ||
55 | |||
56 | class ScreenHinter(object): | ||
57 | # A terrible hack to try to provide some needed context to the | ||
58 | # image widget. | ||
59 | def __init__(self, screen=None): | ||
60 | self.screen = screen | ||
61 | |||
62 | def setScreen(self, screen): | ||
63 | self.screen = screen | ||
64 | |||
65 | def getSize(self): | ||
66 | cols, rows = self.screen.get_cols_rows() | ||
67 | return (cols, rows-1) | ||
68 | |||
69 | class Handout(urwid.WidgetWrap): | ||
70 | def __init__(self, widget, background): | ||
71 | self.background = background | ||
72 | self.pad = SlidePadding(widget, align='center', width='pack') | ||
73 | self.map = urwid.AttrMap(self.pad, self.background) | ||
74 | super(Handout, self).__init__(self.map) | ||
75 | |||
76 | class UrwidSlide(urwid.WidgetWrap): | ||
77 | def __init__(self, title, transition, widget, background): | ||
78 | self.title = title | ||
79 | self.transition = transition | ||
80 | self.fill = SlideFiller(widget) | ||
81 | self.background = background | ||
82 | self.map = urwid.AttrMap(self.fill, self.background) | ||
83 | self.handout = None | ||
84 | self.animations = [] | ||
85 | self.progressives = [] | ||
86 | self.progressive_attr = None | ||
87 | self.progressive_state = 0 | ||
88 | super(UrwidSlide, self).__init__(self.map) | ||
89 | |||
90 | def startAnimation(self, loop): | ||
91 | for x in self.animations: | ||
92 | x.startAnimation(loop) | ||
93 | |||
94 | def stopAnimation(self): | ||
95 | for x in self.animations: | ||
96 | x.stopAnimation() | ||
97 | |||
98 | def resetAnimation(self): | ||
99 | for x in self.animations: | ||
100 | x.resetAnimation() | ||
101 | |||
102 | def resetProgressive(self, on=False): | ||
103 | if on: | ||
104 | self.progressive_state = len(self.progressives) | ||
105 | for x in self.progressives: | ||
106 | x.set_attr_map({None: None}) | ||
107 | else: | ||
108 | self.progressive_state = 0 | ||
109 | for x in self.progressives: | ||
110 | x.set_attr_map({None: self.progressive_attr}) | ||
111 | |||
112 | def nextProgressive(self): | ||
113 | if self.progressive_state >= len(self.progressives): | ||
114 | return False | ||
115 | self.progressives[self.progressive_state].set_attr_map( | ||
116 | {None: None}) | ||
117 | self.progressive_state += 1 | ||
118 | return True | ||
119 | |||
120 | def prevProgressive(self): | ||
121 | if self.progressive_state <= 0: | ||
122 | return False | ||
123 | self.progressive_state -= 1 | ||
124 | self.progressives[self.progressive_state].set_attr_map( | ||
125 | {None: self.progressive_attr}) | ||
126 | return True | ||
127 | |||
128 | def setProgressive(self, state): | ||
129 | self.progressive_state = state | ||
130 | for i, x in enumerate(self.progressives): | ||
131 | if i < self.progressive_state: | ||
132 | x.set_attr_map({None: None}) | ||
133 | else: | ||
134 | x.set_attr_map({None: self.progressive_attr}) | ||
135 | |||
136 | class AnimatedText(urwid.Text): | ||
137 | def __init__(self, interval=0.5, oneshot=False): | ||
138 | super(AnimatedText, self).__init__(u'') | ||
139 | self.frames = [] | ||
140 | self.current = 0 | ||
141 | self.running = False | ||
142 | self.interval = interval | ||
143 | self.oneshot = oneshot | ||
144 | |||
145 | def addFrame(self, text): | ||
146 | self.frames.append(text) | ||
147 | if len(self.frames) == self.current+1: | ||
148 | self.set_text(text) | ||
149 | |||
150 | def startAnimation(self, loop): | ||
151 | if self.running: | ||
152 | return | ||
153 | if len(self.frames) == 1: | ||
154 | return | ||
155 | self.running = True | ||
156 | loop.set_alarm_in(self.interval, self.updateCallback) | ||
157 | |||
158 | def updateCallback(self, loop=None, data=None): | ||
159 | if not self.running: | ||
160 | return | ||
161 | if self.current+1 >= len(self.frames): | ||
162 | if self.oneshot: | ||
163 | self.running = False | ||
164 | return | ||
165 | self.current = 0 | ||
166 | else: | ||
167 | self.current += 1 | ||
168 | self.set_text(self.frames[self.current]) | ||
169 | loop.set_alarm_in(self.interval, self.updateCallback) | ||
170 | |||
171 | def stopAnimation(self): | ||
172 | if not self.running: | ||
173 | return | ||
174 | self.running = False | ||
175 | |||
176 | def resetAnimation(self): | ||
177 | self.current = 0 | ||
178 | self.set_text(self.frames[self.current]) | ||