1
2 '''
3 This device provides a little Gtk window to monitor braille output onscreen.
4 It receives the exact same output as the BrlAPIDevice (if connected) and relys
5 on the exact same default settings inherited from L{Braille.BrailleStyle}.
6
7 Since a window is not exactly a device, we're kind of bending our own rules
8 here. However, implementing the braille monitor as a device seemed the most
9 suitable solution.
10
11 @author: Martina Weicht
12 @organization: IT Science Center Ruegen gGmbH, Germany
13 @copyright: Copyright (c) 2007, 2008 ITSC Ruegen
14 @license: The BSD License
15
16 All rights reserved. This program and the accompanying materials are made
17 available under the terms of the BSD license which accompanies
18 this distribution, and is available at
19 U{http://www.opensource.org/licenses/bsd-license.php}
20 '''
21 import pygtk
22 pygtk.require('2.0')
23 import gtk, gobject
24 import os, time, logging, array, string, re
25 import pango
26 from AccessEngine import AEInput
27 import Braille
28 from Tools.i18n import _
29 from AccessEngine.AEConstants import *
30
31 __uie__ = dict(kind='device')
32
33 log = logging.getLogger('BrailleMonitor')
34
36 '''
37 Settings for BrailleMonitor
38 @note: These are only phony settings for now.
39
40 BrailleMonitor (bool): Show braille output on braille monitor?
41 '''
42 - def init(self, device):
43 self.newBool('ShowMonitor', True, _('Show braille monitor?'),
44 _('When set, the braille monitor will be visible on-screen.'))
45 self.newBool('LargeFont', True, _('Use large font?'),
46 _('When set, a large font will be used to show Braille output \
47 on braille monitor.'))
48 self.newBool('SmallFont', False, _('Use small font?'),
49 _('When set, a small font will be used to show Braille output \
50 on braille monitor.'))
51
52 '''
53 Overrides the base L{Braille.BrailleStyle} class.
54 All properties currently reside in base class.
55 '''
57 '''
58 Gets configurable absolute settings affecting all output from this device.
59
60 @return: Root group of all configurable settings
61 @rtype: L{AEState.Setting.Group}
62 '''
63 root = self.newGroup()
64
65
66
67
68
69
70
71
72
73
74 root.append('ShowMonitor')
75
76 g = root.newGroup(_('Font Size'))
77 g.append('LargeFont')
78 g.append('SmallFont')
79 return root
80
82
83 USE_THREAD = False
84 BRL_MODULE_CNT = 80
85 LABEL_MARKUP = "<span size='large'><b><tt>%s</tt></b></span>"
86 CARET_MARKUP = "<span foreground='blue' size='large'><u><b><tt>%s</tt></b></u></span>"
87 STYLE = BrailleMonitorStyle
88
89
90
91 EOL = '\xc2\xb6'
92 TAB = ' '
93 BRLMON_VISIBLE = False
94
96 '''
97 Creates and shows the monitor window and its components.
98 '''
99 self.commands = []
100 self.last_style = None
101 self.caretpos = 0
102
103
104 self.default_style.DisplayColumns = self.BRL_MODULE_CNT
105 self.default_style.DisplayRows = 1
106 self.default_style.TotalCells = self.BRL_MODULE_CNT
107
108
109
110
111 if not self.BRLMON_VISIBLE:
112 self._createMonitorWindow()
113 self.BRLMON_VISIBLE = True
114
115
116 - def postInit(self):
117 '''
118 Called after the L{init} method and after either
119 L{AccessEngine.AEDevice.AEOutput.Base.AEOutput.loadStyles} or
120 L{AccessEngine.AEDevice.AEOutput.Base.AEOutput.createDistinctStyles}.
121 missingcellcnt is the number of missing (broken) cells defined by the user
122 and stored in the L{Setting} string "CellMask".
123
124 @note: MW: This CellMask setting is part of Braille.BrailleStyle. Since
125 BrailleMonitor inherits from Braille.Braille as does BrlAPIDevice, we are
126 able to access the braille display's settings from here. If no braille
127 display is connected, we do not want any missing cell mask set to our
128 braille monitor. Further testing is needed for this case.
129
130 @raise Error.InitError: When a communication or state problem exists for
131 the specific device
132 '''
133 self.default_style.missingcellcnt = self.default_style.CellMask.count('0')
134
135
137 return _('Shows braille output on screen')
138
140 '''
141 @return: integer containing missing cell count
142 @rtype: integer
143 @raise NotImplementedError: When not overridden in a subclass
144 '''
145 return self.default_style.missingcellcnt
146
148 '''
149 @param style: Style with which the ellipsis are defined
150 @type style: L{AccessEngine.AEOutput.AEOutput.Style}
151 @return: tuple containing length of left and right ellipsis
152 @rtype: tuple
153 @raise NotImplementedError: When not overridden in a subclass
154 '''
155 left = 0
156 right = 0
157
158 if self.default_style.EllipsisLeft:
159 left = len(self.EllipsisStyles[self.default_style.EllipsisStyle][0])
160 if self.default_style.EllipsisRight:
161 right = len(self.EllipsisStyles[self.default_style.EllipsisStyle][1])
162
163 return (left, right)
164
166 '''
167 Creates the window for the braille monitor by setting up as many labels as
168 there are braille modules requested along with the same number of drawing
169 areas so at some point the braille dot pattern per character may be shown
170 underneath the labels. Showing those braille dots should be made optional,
171 so the user decides whether she wants to see them or not.
172 '''
173 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
174
175 self.window.set_transient_for(None)
176 self.window.set_title(_('BrailleMonitor'))
177 self.window.set_accept_focus(False)
178
179
180
181
182 main_vbox = gtk.VBox(False, 0)
183 main_vbox.set_border_width(1)
184 self.window.add(main_vbox)
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 btnbox = gtk.HBox(False, 0)
213
214
215 self.braillemodules = []
216 i = 0
217 while i < self.BRL_MODULE_CNT:
218 self.braillemodules.append( gtk.Label() )
219 self.braillemodules[i].set_markup( self.LABEL_MARKUP % ' ')
220 btnbox.pack_start( self.braillemodules[i], True, True, 0)
221
222 if i < (self.BRL_MODULE_CNT - 1):
223 btnbox.pack_start( gtk.VSeparator(), True, True, 0)
224
225 i += 1
226
227 main_vbox.add(btnbox)
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 self.window.show_all()
244
245
247 '''
248 Adds the given text and associated style to command list. Text will be
249 output to the braille device in sendTalk.
250
251 @param text: String to be output
252 @type text: string
253 @param style: Style with which this string should be output; None means no
254 style change should be applied
255 @type style: integer
256 '''
257 self.commands.append((CMD_STRING, text, style))
258
260 '''
261 Iterates through list of commands and builds output string including user
262 selected ellipsis and caret.
263
264 @param style: Ignored
265 @type style: L{AccessEngine.AEOutput.AEOutput.Style}
266 '''
267 stream = []
268 truncateleft = False
269 truncateright = False
270
271 for command, value, style in self.commands:
272 if style is not None and (style.isDirty() or self.last_style != style):
273 self.last_style = style
274 if command is CMD_STRING:
275 if value is not None:
276 stream.append(value)
277 elif command is CMD_TRUNCATE:
278 truncateleft = value[0]
279 truncateright = value[1]
280
281
282 outarray = array.array('u', ''.join(stream))
283
284 self._clear()
285 self._showText(outarray)
286
287 self.commands = []
288
289
291 '''
292 Stops braille output immediately.
293
294 @param style: Ignored
295 @type style: L{AccessEngine.AEOutput.AEOutput.Style}
296 '''
297 self.commands = []
298
299
301 '''
302 Nur zum Testen der Untermenüs
303 '''
304 print 'Test submenu'
305
306
308 '''
309 Clears Braille monitor of all contents.
310 '''
311 i = 0
312 while i < self.BRL_MODULE_CNT:
313 self.braillemodules[i].set_label( ' ' )
314 i += 1
315
316
317 - def _showText(self, textArray):
318 '''
319 Set the given text as labels
320
321 @note: MW: For now the caret on the BrailleMonitor will be styled according
322 to some fixed mark-up. Once a settings dialog has been created for the
323 BrailleMonitor, this needs to be changed.
324
325 @param textArray: The text do be displayed
326 @type textArray: array
327 '''
328
329
330
331
332
333
334
335 i = 0
336 while i < len(textArray) and i < self.BRL_MODULE_CNT:
337 if i == self.caretpos:
338 self.braillemodules[i].set_markup( self.CARET_MARKUP % textArray[i] )
339 else:
340 self.braillemodules[i].set_markup( self.LABEL_MARKUP % textArray[i] )
341 i += 1
342
343
345 '''
346 Overwrites the same method in Braille.Braille
347 Is this the correct place to replace tab and eol characters?
348
349 @param text: Text to be parsed
350 @type text: string
351 @param style: Style object defining how the text should be parsed
352 @type style: L{AccessEngine.AEOutput.AEOutput.Style}
353 @param por: Point of regard for the first character in the text, or None if
354 the text is not associated with a POR
355 @type por: L{AEPor}
356 @param sem: Semantic tag for the text
357 @type sem: integer
358 @return: Parsed words
359 @rtype: 3-tuple of lists of string, L{AEPor},
360 L{AccessEngine.AEOutput.AEOutput.Style}
361 '''
362
363
364 text = text.replace('\n', self.EOL)
365 text = text.replace('\t', self.TAB)
366
367 return [(text, por, style)]
368
369
371 '''
372 Sends the current caret position relative to the first cell (zero-offset)
373 on the device. The style object is used by the device in deciding how the
374 caret should be presented.
375
376 @note: braille monitor is zero-based. No offset here.
377 @param pos: Zero-offset cell position of the caret, up to the device to
378 change to one-offset if need be
379 @type pos: string
380 @param style: Style with which the caret should be indicated
381 @type style: L{AccessEngine.AEOutput.AEOutput.Style}
382 @raise NotImplementedError: When not overridden in a subclass
383 '''
384 self.caretpos = pos
385
387 '''
388 Closes the braille monitor.
389 '''
390 self.window.destroy()
391 self.window = None
392 self.commands = []
393 self.BRLMON_VISIBLE = False
394