Coverage Report - orca.speechgenerator

ModuleCoverage %
orca.speechgenerator
70%
1
# Orca
2
#
3
# Copyright 2005-2007 Sun Microsystems Inc.
4
#
5
# This library is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU Library General Public
7
# License as published by the Free Software Foundation; either
8
# version 2 of the License, or (at your option) any later version.
9
#
10
# This library is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
# Library General Public License for more details.
14
#
15
# You should have received a copy of the GNU Library General Public
16
# License along with this library; if not, write to the
17
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
# Boston, MA 02111-1307, USA.
19
20
"""Utilities for obtaining speech utterances for objects.  In general,
21
there probably should be a singleton instance of the SpeechGenerator
22
class.  For those wishing to override the speech generators, however,
23
one can create a new instance and replace/extend the speech generators
24 1
as they see fit."""
25
26 1
__id__        = "$Id: speechgenerator.py 2126 2007-03-06 21:35:17Z richb $"
27 1
__version__   = "$Revision: 2126 $"
28 1
__date__      = "$Date: 2007-03-06 13:35:17 -0800 (Tue, 06 Mar 2007) $"
29 1
__copyright__ = "Copyright (c) 2005-2006 Sun Microsystems Inc."
30 1
__license__   = "LGPL"
31
32 1
import math
33
34 1
import atspi
35 1
import debug
36 1
import orca_state
37 1
import rolenames
38 1
import settings
39
40 1
from orca_i18n import _                          # for gettext support
41
42 2
class SpeechGenerator:
43
    """Takes accessible objects and produces a string to speak for
44
    those objects.  See the getSpeech method, which is the primary
45
    entry point.  Subclasses can feel free to override/extend the
46
    speechGenerators instance field as they see fit."""
47
48 1
    def __init__(self, script):
49
50
        # The script that created us.  This allows us to ask the
51
        # script for information if we need it.
52
        #
53 61
        self._script = script
54
55
        # Set up a dictionary that maps role names to functions
56
        # that generate speech for objects that implement that role.
57
        #
58 61
        self.speechGenerators = {}
59 61
        self.speechGenerators[rolenames.ROLE_ALERT]               = \
60
             self._getSpeechForAlert
61 61
        self.speechGenerators[rolenames.ROLE_ANIMATION]           = \
62
             self._getSpeechForAnimation
63 61
        self.speechGenerators[rolenames.ROLE_ARROW]               = \
64
             self._getSpeechForArrow
65 61
        self.speechGenerators[rolenames.ROLE_CHECK_BOX]           = \
66
             self._getSpeechForCheckBox
67 61
        self.speechGenerators[rolenames.ROLE_CHECK_MENU]          = \
68
             self._getSpeechForCheckMenuItem
69 61
        self.speechGenerators[rolenames.ROLE_CHECK_MENU_ITEM]     = \
70
             self._getSpeechForCheckMenuItem
71 61
        self.speechGenerators[rolenames.ROLE_COLUMN_HEADER]       = \
72
             self._getSpeechForColumnHeader
73 61
        self.speechGenerators[rolenames.ROLE_COMBO_BOX]           = \
74
             self._getSpeechForComboBox
75 61
        self.speechGenerators[rolenames.ROLE_DESKTOP_ICON]        = \
76
             self._getSpeechForDesktopIcon
77 61
        self.speechGenerators[rolenames.ROLE_DIAL]                = \
78
             self._getSpeechForDial
79 61
        self.speechGenerators[rolenames.ROLE_DIALOG]              = \
80
             self._getSpeechForDialog
81 61
        self.speechGenerators[rolenames.ROLE_DIRECTORY_PANE]      = \
82
             self._getSpeechForDirectoryPane
83 61
        self.speechGenerators[rolenames.ROLE_FRAME]               = \
84
             self._getSpeechForFrame
85 61
        self.speechGenerators[rolenames.ROLE_HTML_CONTAINER]      = \
86
             self._getSpeechForHtmlContainer
87 61
        self.speechGenerators[rolenames.ROLE_ICON]                = \
88
             self._getSpeechForIcon
89 61
        self.speechGenerators[rolenames.ROLE_IMAGE]               = \
90
             self._getSpeechForImage
91 61
        self.speechGenerators[rolenames.ROLE_LABEL]               = \
92
             self._getSpeechForLabel
93 61
        self.speechGenerators[rolenames.ROLE_LAYERED_PANE]        = \
94
             self._getSpeechForLayeredPane
95 61
        self.speechGenerators[rolenames.ROLE_LIST]                = \
96
             self._getSpeechForList
97 61
        self.speechGenerators[rolenames.ROLE_MENU]                = \
98
             self._getSpeechForMenu
99 61
        self.speechGenerators[rolenames.ROLE_MENU_BAR]            = \
100
             self._getSpeechForMenuBar
101 61
        self.speechGenerators[rolenames.ROLE_MENU_ITEM]           = \
102
             self._getSpeechForMenuItem
103 61
        self.speechGenerators[rolenames.ROLE_OPTION_PANE]         = \
104
             self._getSpeechForOptionPane
105 61
        self.speechGenerators[rolenames.ROLE_PAGE_TAB]            = \
106
             self._getSpeechForPageTab
107 61
        self.speechGenerators[rolenames.ROLE_PAGE_TAB_LIST]       = \
108
             self._getSpeechForPageTabList
109 61
        self.speechGenerators[rolenames.ROLE_PARAGRAPH]           = \
110
             self._getSpeechForText
111 61
        self.speechGenerators[rolenames.ROLE_PASSWORD_TEXT]       = \
112
             self._getSpeechForText
113 61
        self.speechGenerators[rolenames.ROLE_PROGRESS_BAR]        = \
114
             self._getSpeechForProgressBar
115 61
        self.speechGenerators[rolenames.ROLE_PUSH_BUTTON]         = \
116
             self._getSpeechForPushButton
117 61
        self.speechGenerators[rolenames.ROLE_RADIO_BUTTON]        = \
118
             self._getSpeechForRadioButton
119 61
        self.speechGenerators[rolenames.ROLE_RADIO_MENU]          = \
120
             self._getSpeechForRadioMenuItem
121 61
        self.speechGenerators[rolenames.ROLE_RADIO_MENU_ITEM]     = \
122
             self._getSpeechForRadioMenuItem
123 61
        self.speechGenerators[rolenames.ROLE_ROW_HEADER]          = \
124
             self._getSpeechForRowHeader
125 61
        self.speechGenerators[rolenames.ROLE_SCROLL_BAR]          = \
126
             self._getSpeechForScrollBar
127 61
        self.speechGenerators[rolenames.ROLE_SLIDER]              = \
128
             self._getSpeechForSlider
129 61
        self.speechGenerators[rolenames.ROLE_SPIN_BUTTON]         = \
130
             self._getSpeechForSpinButton
131 61
        self.speechGenerators[rolenames.ROLE_SPLIT_PANE]          = \
132
             self._getSpeechForSplitPane
133 61
        self.speechGenerators[rolenames.ROLE_TABLE]               = \
134
             self._getSpeechForTable
135 61
        self.speechGenerators[rolenames.ROLE_TABLE_CELL]          = \
136
             self._getSpeechForTableCellRow
137 61
        self.speechGenerators[rolenames.ROLE_TABLE_COLUMN_HEADER] = \
138
             self._getSpeechForTableColumnHeader
139 61
        self.speechGenerators[rolenames.ROLE_TABLE_ROW_HEADER]    = \
140
             self._getSpeechForTableRowHeader
141 61
        self.speechGenerators[rolenames.ROLE_TEAR_OFF_MENU_ITEM]  = \
142
             self._getSpeechForMenu
143 61
        self.speechGenerators[rolenames.ROLE_TERMINAL]            = \
144
             self._getSpeechForTerminal
145 61
        self.speechGenerators[rolenames.ROLE_TEXT]                = \
146
             self._getSpeechForText
147 61
        self.speechGenerators[rolenames.ROLE_TOGGLE_BUTTON]       = \
148
             self._getSpeechForToggleButton
149 61
        self.speechGenerators[rolenames.ROLE_TOOL_BAR]            = \
150
             self._getSpeechForToolBar
151 61
        self.speechGenerators[rolenames.ROLE_TREE]                = \
152
             self._getSpeechForTable
153 61
        self.speechGenerators[rolenames.ROLE_TREE_TABLE]          = \
154
             self._getSpeechForTable
155 61
        self.speechGenerators[rolenames.ROLE_WINDOW]              = \
156
             self._getSpeechForWindow
157
158 1
    def _getSpeechForObjectAccelerator(self, obj):
159
        """Returns a list of utterances that describes the keyboard
160
        accelerator (and possibly shortcut) for the given object.
161
162
        Arguments:
163
        - obj: the Accessible object
164
165
        Returns a list of utterances to be spoken.
166
        """
167
168 220
        result = self._script.getAcceleratorAndShortcut(obj)
169
170 220
        accelerator = result[0]
171
        #shortcut = result[1]
172
173 220
        utterances = []
174
175
        # [[[TODO: WDW - various stuff preserved while we work out the
176
        # desired verbosity here.]]]
177
        #
178
        #if len(shortcut) > 0:
179
        #    utterances.append(_("shortcut") + " " + shortcut)
180
        #    utterances.append(accelerator)
181 220
        if len(accelerator) > 0:
182
            #utterances += (_("accelerator") + " " + accelerator)
183 40
            utterances.append(accelerator)
184
185 220
        return utterances
186
187 1
    def _getSpeechForObjectAvailability(self, obj):
188
        """Returns a list of utterances that describes the availability
189
        of the given object.
190
191
        Arguments:
192
        - obj: the Accessible object
193
194
        Returns a list of utterances to be spoken.
195
        """
196 644
        if obj.state.count(atspi.Accessibility.STATE_SENSITIVE) == 0:
197 1
            return [_("grayed")]
198
        else:
199 643
            return []
200
201 1
    def _getSpeechForObjectLabel(self, obj):
202 556
        label = self._script.getDisplayedLabel(obj)
203 556
        if label:
204 47
            return [label]
205
        else:
206 509
            return []
207
208 1
    def _getSpeechForObjectName(self, obj):
209 658
        name = self._script.getDisplayedText(obj)
210 658
        if name:
211 550
            return [name]
212 108
        elif obj.description:
213 16
            return [obj.description]
214
        else:
215 92
            return []
216
217 1
    def _getSpeechForObjectRole(self, obj):
218 548
        if (obj.role != rolenames.ROLE_UNKNOWN):
219 548
            return [rolenames.getSpeechForRoleName(obj)]
220
        else:
221 0
            return []
222
223 1
    def _debugGenerator(self, generatorName, obj, already_focused, utterances):
224
        """Prints debug.LEVEL_FINER information regarding the speech generator.
225
226
        Arguments:
227
        - generatorName: the name of the generator
228
        - obj: the object being presented
229
        - already_focused: False if object just received focus
230
        - utterances: the generated text
231
        """
232
233 1519
        debug.println(debug.LEVEL_FINER,
234 1519
                      "GENERATOR: %s" % generatorName)
235 1519
        debug.println(debug.LEVEL_FINER,
236 1519
                      "           obj             = %s" % obj.name)
237 1519
        debug.println(debug.LEVEL_FINER,
238 1519
                      "           role            = %s" % obj.role)
239 1519
        debug.println(debug.LEVEL_FINER,
240 1519
                      "           already_focused = %s" % already_focused)
241 1519
        debug.println(debug.LEVEL_FINER,
242 1519
                      "           utterances:")
243 4606
        for text in utterances:
244 3087
            debug.println(debug.LEVEL_FINER,
245 3087
                      "               (%s)" % text)
246
247 1
    def _getDefaultSpeech(self, obj, already_focused):
248
        """Gets a list of utterances to be spoken for the current
249
        object's name, role, and any accelerators.  This is usually the
250
        fallback speech generator should no other specialized speech
251
        generator exist for this object.
252
253
        The default speech will be of the following form:
254
255
        label name role availability
256
257
        Arguments:
258
        - obj: an Accessible
259
        - already_focused: False if object just received focus
260
261
        Returns a list of utterances to be spoken for the object.
262
        """
263
264 347
        utterances = []
265
266 347
        if not already_focused:
267 347
            label = self._getSpeechForObjectLabel(obj)
268 347
            utterances.extend(label)
269 347
            name = self._getSpeechForObjectName(obj)
270 347
            if name != label:
271 331
                utterances.extend(name)
272 347
            utterances.extend(self._getSpeechForObjectRole(obj))
273
274 347
        utterances.extend(self._getSpeechForObjectAvailability(obj))
275
276 347
        self._debugGenerator("_getDefaultSpeech",
277 347
                             obj,
278 347
                             already_focused,
279 347
                             utterances)
280
281 347
        return utterances
282
283 1
    def _getSpeechForAlert(self, obj, already_focused):
284
        """Gets the title of the dialog and the contents of labels inside the
285
        dialog that are not associated with any other objects.
286
287
        Arguments:
288
        - obj: the Accessible dialog
289
        - already_focused: False if object just received focus
290
291
        Returns a list of utterances be spoken.
292
        """
293
294 14
        utterances = []
295 14
        label = self._getSpeechForObjectLabel(obj)
296 14
        utterances.extend(label)
297 14
        name = self._getSpeechForObjectName(obj)
298 14
        if name != label:
299 12
            utterances.extend(name)
300
301
        # Find all the unrelated labels in the dialog and speak them.
302
        #
303 14
        labels = self._script.findUnrelatedLabels(obj)
304 44
        for label in labels:
305 30
            utterances.append(label.name)
306
307 14
        self._debugGenerator("_getSpeechForAlert",
308 14
                             obj,
309 14
                             already_focused,
310 14
                             utterances)
311
312 14
        return utterances
313
314 1
    def _getSpeechForAnimation(self, obj, already_focused):
315
        """Gets the speech for an animation.
316
317
        Arguments:
318
        - obj: the animation
319
        - already_focused: False if object just received focus
320
321
        Returns a list of utterances to be spoken.
322
        """
323
324 0
        utterances = []
325 0
        label = self._getSpeechForObjectLabel(obj)
326 0
        utterances.extend(label)
327 0
        name = self._getSpeechForObjectName(obj)
328 0
        if name != label:
329 0
            utterances.extend(name)
330
331 0
        self._debugGenerator("_getSpeechForAnimation",
332 0
                             obj,
333 0
                             already_focused,
334 0
                             utterances)
335
336 0
        return utterances
337
338 1
    def _getSpeechForArrow(self, obj, already_focused):
339
        """Gets a list of utterances to be spoken for an arrow.
340
341
        Arguments:
342
        - obj: the arrow
343
        - already_focused: False if object just received focus
344
345
        Returns a list of utterances to be spoken for the object.
346
        """
347
348
        # [[[TODO: determine orientation of arrow.  Logged as bugzilla bug
349
        # 319744.]]]
350
        # text = arrow direction (left, right, up, down)
351
        #
352 0
        utterances = self._getDefaultSpeech(obj, already_focused)
353
354 0
        self._debugGenerator("_getSpeechForArrow",
355 0
                             obj,
356 0
                             already_focused,
357 0
                             utterances)
358
359 0
        return utterances
360
361 1
    def _getSpeechForCheckBox(self, obj, already_focused):
362
        """Get the speech for a check box.  If the check box already had
363
        focus, then only the state is spoken.
364
365
        Arguments:
366
        - obj: the check box
367
        - already_focused: False if object just received focus
368
369
        Returns a list of utterances to be spoken for the object.
370
        """
371
372 129
        utterances = []
373 129
        if obj.state.count(atspi.Accessibility.STATE_CHECKED):
374 51
            checkedState = _("checked")
375
        else:
376 78
            checkedState = _("not checked")
377
378
        # If it's not already focused, say it's name
379
        #
380 129
        if not already_focused:
381 123
            label = self._getSpeechForObjectLabel(obj)
382 123
            utterances.extend(label)
383 123
            name = self._getSpeechForObjectName(obj)
384 123
            if name != label:
385 54
                utterances.extend(name)
386 123
            utterances.extend(self._getSpeechForObjectRole(obj))
387 123
            utterances.append(checkedState)
388 123
            utterances.extend(self._getSpeechForObjectAvailability(obj))
389
        else:
390 6
            utterances.append(checkedState)
391
392 129
        self._debugGenerator("_getSpeechForCheckBox",
393 129
                             obj,
394 129
                             already_focused,
395 129
                             utterances)
396
397 129
        return utterances
398
399 1
    def _getSpeechForCheckMenuItem(self, obj, already_focused):
400
        """Get the speech for a check menu item.  If the check menu item
401
        already had focus, then only the state is spoken.
402
403
        Arguments:
404
        - obj: the check menu item
405
        - already_focused: False if object just received focus
406
407
        Returns a list of utterances to be spoken for the object.
408
        """
409
410 23
        utterances = self._getSpeechForCheckBox(obj, already_focused)
411
412 23
        if (settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE)\
413
           and not already_focused:
414 23
            utterances.extend(self._getSpeechForObjectAccelerator(obj))
415
416 23
        self._debugGenerator("_getSpeechForCheckMenuItem",
417 23
                             obj,
418 23
                             already_focused,
419 23
                             utterances)
420
421 23
        return utterances
422
423 1
    def _getSpeechForColumnHeader(self, obj, already_focused):
424
        """Get the speech for a column header.
425
426
        Arguments:
427
        - obj: the column header
428
        - already_focused: False if object just received focus
429
430
        Returns a list of utterances to be spoken for the object.
431
        """
432
433 21
        utterances = self._getDefaultSpeech(obj, already_focused)
434
435 21
        self._debugGenerator("_getSpeechForColumnHeader",
436 21
                             obj,
437 21
                             already_focused,
438 21
                             utterances)
439
440 21
        return utterances
441
442 1
    def _getSpeechForComboBox(self, obj, already_focused):
443
        """Get the speech for a combo box.  If the combo box already has focus,
444
        then only the selection is spoken.
445
446
        Arguments:
447
        - obj: the combo box
448
        - already_focused: False if object just received focus
449
450
        Returns a list of utterances to be spoken for the object.
451
        """
452
453 40
        utterances = []
454
455 40
        if not already_focused:
456 30
            label = self._getSpeechForObjectLabel(obj)
457 30
            utterances.extend(label)
458
        else:
459 10
            label = None
460
461 40
        name = self._getSpeechForObjectName(obj)
462 40
        if name != label:
463 37
            utterances.extend(name)
464
465 40
        if not already_focused:
466 30
            utterances.extend(self._getSpeechForObjectRole(obj))
467
468 40
        utterances.extend(self._getSpeechForObjectAvailability(obj))
469
470 40
        self._debugGenerator("_getSpeechForComboBox",
471 40
                             obj,
472 40
                             already_focused,
473 40
                             utterances)
474
475 40
        return utterances
476
477 1
    def _getSpeechForDesktopIcon(self, obj, already_focused):
478
        """Get the speech for a desktop icon.
479
480
        Arguments:
481
        - obj: the desktop icon
482
        - already_focused: False if object just received focus
483
484
        Returns a list of utterances to be spoken for the object.
485
        """
486
487 0
        utterances = self._getDefaultSpeech(obj, already_focused)
488
489 0
        self._debugGenerator("_getSpeechForDesktopIcon",
490 0
                             obj,
491 0
                             already_focused,
492 0
                             utterances)
493
494 0
        return utterances
495
496 1
    def _getSpeechForDial(self, obj, already_focused):
497
        """Get the speech for a dial.
498
499
        Arguments:
500
        - obj: the dial
501
        - already_focused: False if object just received focus
502
503
        Returns a list of utterances to be spoken for the object.
504
        """
505
506
        # [[[TODO: WDW - might need to include the value here?  Logged as
507
        # bugzilla bug 319746.]]]
508
        #
509 0
        utterances = self._getDefaultSpeech(obj, already_focused)
510
511 0
        self._debugGenerator("_getSpeechForDial",
512 0
                             obj,
513 0
                             already_focused,
514 0
                             utterances)
515
516 0
        return utterances
517
518 1
    def _getSpeechForDialog(self, obj, already_focused):
519
        """Get the speech for a dialog box.
520
521
        Arguments:
522
        - obj: the dialog box
523
        - already_focused: False if object just received focus
524
525
        Returns a list of utterances to be spoken for the object.
526
        """
527
528 10
        utterances = self._getSpeechForAlert(obj, already_focused)
529
530 10
        self._debugGenerator("_getSpeechForDialog",
531 10
                             obj,
532 10
                             already_focused,
533 10
                             utterances)
534
535 10
        return utterances
536
537 1
    def _getSpeechForDirectoryPane(self, obj, already_focused):
538
        """Get the speech for a directory pane.
539
540
        Arguments:
541
        - obj: the dial
542
        - already_focused: False if object just received focus
543
544
        Returns a list of utterances to be spoken for the object.
545
        """
546
547 0
        utterances = self._getDefaultSpeech(obj, already_focused)
548
549 0
        self._debugGenerator("_getSpeechForDirectoryPane",
550 0
                             obj,
551 0
                             already_focused,
552 0
                             utterances)
553
554 0
        return utterances
555
556 1
    def _getSpeechForFrame(self, obj, already_focused):
557
        """Get the speech for a frame.
558
559
        Arguments:
560
        - obj: the frame
561
        - already_focused: False if object just received focus
562
563
        Returns a list of utterances to be spoken for the object.
564
        """
565
566
        # [[[TODO: richb - readjusted to just get the default speech instead
567
        # of treating the frame like an alert and speaking all unrelated
568
        # labels. We'll need to see if this has any adverse effects and
569
        # adjust accordingly.]]]
570
        #
571 39
        utterances = self._getDefaultSpeech(obj, already_focused)
572
        #utterances = self._getSpeechForAlert(obj, already_focused)
573
574 39
        self._debugGenerator("_getSpeechForFrame",
575 39
                             obj,
576 39
                             already_focused,
577 39
                             utterances)
578
579 39
        return utterances
580
581 1
    def _getSpeechForHtmlContainer(self, obj, already_focused):
582
        """Get the speech for an HTML container.
583
584
        Arguments:
585
        - obj: the dial
586
        - already_focused: False if object just received focus
587
588
        Returns a list of utterances to be spoken for the object.
589
        """
590
591 0
        utterances = self._getDefaultSpeech(obj, already_focused)
592
593 0
        self._debugGenerator("_getSpeechForHtmlContainer",
594 0
                             obj,
595 0
                             already_focused,
596 0
                             utterances)
597
598 0
        return utterances
599
600 1
    def _getSpeechForIcon(self, obj, already_focused):
601
        """Get the speech for an icon.
602
603
        Arguments:
604
        - obj: the icon
605
        - already_focused: False if object just received focus
606
607
        Returns a list of utterances to be spoken for the object.
608
        """
609
610
        # [[[TODO: WDW - HACK to remove availability output because nautilus
611
        # doesn't include this information for desktop icons.  If, at some
612
        # point, it is determined that availability should be added back in,
613
        # then a custom script for nautilus needs to be written to remove the
614
        # availability.]]]
615
        #
616 0
        utterances = []
617 0
        label = self._getSpeechForObjectLabel(obj)
618 0
        utterances.extend(label)
619 0
        name = self._getSpeechForObjectName(obj)
620 0
        if name != label:
621 0
            utterances.extend(name)
622
623 0
        if obj.image:
624 0
            description = obj.image.imageDescription
625 0
            if description and len(description):
626 0
                utterances.append(description)
627
628 0
        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
629 0
            utterances.append(rolenames.getSpeechForRoleName(obj))
630
631 0
        self._debugGenerator("_getSpeechForIcon",
632 0
                             obj,
633 0
                             already_focused,
634 0
                             utterances)
635
636 0
        return utterances
637
638 1
    def _getSpeechForImage(self, obj, already_focused):
639
        """Get the speech for an image.
640
641
        Arguments:
642
        - obj: the image
643
        - already_focused: False if object just received focus
644
645
        Returns a list of utterances to be spoken for the object.
646
        """
647
648 0
        utterances = self._getDefaultSpeech(obj, already_focused)
649
650 0
        self._debugGenerator("_getSpeechForImage",
651 0
                             obj,
652 0
                             already_focused,
653 0
                             utterances)
654
655 0
        return utterances
656
657 1
    def _getSpeechForLabel(self, obj, already_focused):
658
        """Get the speech for a label.
659
660
        Arguments:
661
        - obj: the label
662
        - already_focused: False if object just received focus
663
664
        Returns a list of utterances to be spoken for the object.
665
        """
666
667 2
        utterances = self._getDefaultSpeech(obj, already_focused)
668
669 2
        self._debugGenerator("_getSpeechForLabel",
670 2
                             obj,
671 2
                             already_focused,
672 2
                             utterances)
673
674 2
        return utterances
675
676 1
    def _getSpeechForLayeredPane(self, obj, already_focused):
677
        """Get the speech for a layered pane
678
679
        Arguments:
680
        - obj: the table
681
        - already_focused: False if object just received focus
682
683
        Returns a list of utterances to be spoken for the object.
684
        """
685
686 3
        utterances = self._getDefaultSpeech(obj, already_focused)
687
688 3
        self._debugGenerator("_getSpeechForLayeredPane",
689 3
                             obj,
690 3
                             already_focused,
691 3
                             utterances)
692
693
        # If this has no children, then let the user know.
694
        #
695 3
        hasItems = False
696 3
        for i in range(0, obj.childCount):
697 0
            child = obj.child(i)
698 0
            if child.state.count(atspi.Accessibility.STATE_SHOWING):
699 0
                hasItems = True
700 0
                break
701 3
        if not hasItems:
702 3
            utterances.append(_("0 items"))
703
704 3
        return utterances
705
706 1
    def _getSpeechForList(self, obj, already_focused):
707
        """Get the speech for a list.
708
709
        Arguments:
710
        - obj: the list
711
        - already_focused: False if object just received focus
712
713
        Returns a list of utterances to be spoken for the object.
714
        """
715
716
        # [[[TODO: WDW - include how many items in the list?
717
        # Logged as bugzilla bug 319749.]]]
718
        #
719 0
        utterances = self._getDefaultSpeech(obj, already_focused)
720
721 0
        self._debugGenerator("_getSpeechForList",
722 0
                             obj,
723 0
                             already_focused,
724 0
                             utterances)
725
726 0
        return utterances
727
728 1
    def _getSpeechForMenu(self, obj, already_focused):
729
        """Get the speech for a menu.
730
731
        Arguments:
732
        - obj: the menu
733
        - already_focused: False if object just received focus
734
735
        Returns a list of utterances to be spoken for the object.
736
        """
737
738 81
        utterances = self._getDefaultSpeech(obj, already_focused)
739
740 81
        if (obj == orca_state.locusOfFocus) \
741
               and (settings.speechVerbosityLevel \
742
                    == settings.VERBOSITY_LEVEL_VERBOSE):
743 81
            utterances.extend(self._getSpeechForObjectAccelerator(obj))
744
745 81
        self._debugGenerator("_getSpeechForMenu",
746 81
                             obj,
747 81
                             already_focused,
748 81
                             utterances)
749
750 81
        return utterances
751
752 1
    def _getSpeechForMenuBar(self, obj, already_focused):
753
        """Get the speech for a menu bar.
754
755
        Arguments:
756
        - obj: the menu bar
757
        - already_focused: False if object just received focus
758
759
        Returns a list of utterances to be spoken for the object.
760
        """
761
762 2
        utterances = self._getDefaultSpeech(obj, already_focused)
763
764 2
        self._debugGenerator("_getSpeechForMenuBar",
765 2
                             obj,
766 2
                             already_focused,
767 2
                             utterances)
768
769 2
        return utterances
770
771 1
    def _getSpeechForMenuItem(self, obj, already_focused):
772
        """Get the speech for a menu item.
773
774
        Arguments:
775
        - obj: the menu item
776
        - already_focused: False if object just received focus
777
778
        Returns a list of utterances to be spoken for the object.
779
        """
780
781
        # No need to say "menu item" because we already know that.
782
        #
783 116
        utterances = self._getSpeechForObjectName(obj)
784 116
        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
785 116
            utterances.extend(self._getSpeechForObjectAvailability(obj))
786 116
            utterances.extend(self._getSpeechForObjectAccelerator(obj))
787
788 116
        self._debugGenerator("_getSpeechForMenuItem",
789 116
                             obj,
790 116
                             already_focused,
791 116
                             utterances)
792
793 116
        return utterances
794
795 1
    def _getSpeechForText(self, obj, already_focused):
796
        """Get the speech for a text component.
797
798
        Arguments:
799
        - obj: the text component
800
        - already_focused: False if object just received focus
801
802
        Returns a list of utterances to be spoken for the object.
803
        """
804
805
        # [[[TODO: WDW - HACK to remove availability because some text
806
        # areas, such as those in yelp, come up as insensitive though
807
        # they really are ineditable.]]]
808
        #
809 30
        utterances = []
810 30
        utterances.extend(self._getSpeechForObjectLabel(obj))
811 30
        if len(utterances) == 0:
812 10
            if obj.name and (len(obj.name)):
813 0
                utterances.append(obj.name)
814 30
        if obj.role != rolenames.ROLE_PARAGRAPH:
815 30
            utterances.extend(self._getSpeechForObjectRole(obj))
816
817 30
        [text, caretOffset, startOffset] = self._script.getTextLineAtCaret(obj)
818 30
        utterances.append(text)
819
820 30
        self._debugGenerator("_getSpeechForText",
821 30
                             obj,
822 30
                             already_focused,
823 30
                             utterances)
824
825 30
        return utterances
826
827 1
    def _getSpeechForOptionPane(self, obj, already_focused):
828
        """Get the speech for an option pane.
829
830
        Arguments:
831
        - obj: the option pane
832
        - already_focused: False if object just received focus
833
834
        Returns a list of utterances to be spoken for the object.
835
        """
836
837 0
        utterances = self._getDefaultSpeech(obj, already_focused)
838
839 0
        self._debugGenerator("_getSpeechForOptionPane",
840 0
                             obj,
841 0
                             already_focused,
842 0
                             utterances)
843
844 0
        return utterances
845
846 1
    def _getSpeechForPageTab(self, obj, already_focused):
847
        """Get the speech for a page tab.
848
849
        Arguments:
850
        - obj: the page tab
851
        - already_focused: False if object just received focus
852
853
        Returns a list of utterances to be spoken for the object.
854
        """
855
856 32
        utterances = self._getDefaultSpeech(obj, already_focused)
857
858 32
        self._debugGenerator("_getSpeechForPageTab",
859 32
                             obj,
860 32
                             already_focused,
861 32
                             utterances)
862
863 32
        return utterances
864
865 1
    def _getSpeechForPageTabList(self, obj, already_focused):
866
        """Get the speech for a page tab list.
867
868
        Arguments:
869
        - obj: the page tab list
870
        - already_focused: False if object just received focus
871
872
        Returns a list of utterances to be spoken for the object.
873
        """
874
875 6
        utterances = self._getDefaultSpeech(obj, already_focused)
876
877
        #if obj.childCount == 1:
878
        #    utterances.append(_("one tab"))
879
        #else:
880
        #    utterances.append(("%d " % obj.childCount) + _("tabs"))
881
882 6
        self._debugGenerator("_getSpeechForPageTabList",
883 6
                             obj,
884 6
                             already_focused,
885 6
                             utterances)
886
887 6
        return utterances
888
889 1
    def _getSpeechForProgressBar(self, obj, already_focused):
890
        """Get the speech for a progress bar.  If the object already
891
        had focus, just the new value is spoken.
892
893
        Arguments:
894
        - obj: the progress bar
895
        - already_focused: False if object just received focus
896
897
        Returns a list of utterances to be spoken for the object.
898
        """
899
900 0
        percentage = ("%d" % obj.value.currentValue) + " " \
901
                     + _("percent") + ". "
902
903 0
        utterances = []
904
905 0
        if not already_focused:
906 0
            label = self._getSpeechForObjectLabel(obj)
907 0
            utterances.extend(label)
908 0
            name = self._getSpeechForObjectName(obj)
909 0
            if name != label:
910 0
                utterances.extend(name)
911 0
            utterances.extend(self._getSpeechForObjectRole(obj))
912
913 0
        utterances.append(percentage)
914
915 0
        self._debugGenerator("_getSpeechForProgressBar",
916 0
                             obj,
917 0
                             already_focused,
918 0
                             utterances)
919
920 0
        return utterances
921
922 1
    def _getSpeechForPushButton(self, obj, already_focused):
923
        """Get the speech for a push button
924
925
        Arguments:
926
        - obj: the push button
927
        - already_focused: False if object just received focus
928
929
        Returns a list of utterances to be spoken for the object.
930
        """
931
932 137
        utterances = self._getDefaultSpeech(obj, already_focused)
933
934 137
        self._debugGenerator("_getSpeechForPushButton",
935 137
                             obj,
936 137
                             already_focused,
937 137
                             utterances)
938
939 137
        return utterances
940
941 1
    def _getSpeechForRadioButton(self, obj, already_focused):
942
        """Get the speech for a radio button.  If the button already had
943
        focus, then only the state is spoken.
944
945
        Arguments:
946
        - obj: the check box
947
        - already_focused: False if object just received focus
948
949
        Returns a list of utterances to be spoken for the object.
950
        """
951
952 6
        utterances = []
953 6
        if obj.state.count(atspi.Accessibility.STATE_CHECKED):
954 6
            selectionState = _("selected")
955
        else:
956 0
            selectionState = _("not selected")
957
958
        # If it's not already focused, say it's name
959
        #
960 6
        if not already_focused:
961
            # The label is handled as a context in default.py
962
            #
963
            #utterances.extend(self._getSpeechForObjectLabel(obj))
964 6
            utterances.extend(self._getSpeechForObjectName(obj))
965 6
            utterances.append(selectionState)
966 6
            utterances.extend(self._getSpeechForObjectRole(obj))
967 6
            utterances.extend(self._getSpeechForObjectAvailability(obj))
968
        else:
969 0
            utterances.append(selectionState)
970
971 6
        self._debugGenerator("_getSpeechForRadioButton",
972 6
                             obj,
973 6
                             already_focused,
974 6
                             utterances)
975
976 6
        return utterances
977
978 1
    def _getSpeechForRadioMenuItem(self, obj, already_focused):
979
        """Get the speech for a radio menu item.  If the menu item
980
        already had focus, then only the state is spoken.
981
982
        Arguments:
983
        - obj: the check menu item
984
        - already_focused: False if object just received focus
985
986
        Returns a list of utterances to be spoken for the object.
987
        """
988
989 0
        utterances = self._getSpeechForRadioButton(obj, False)
990
991 0
        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
992 0
            utterances.extend(self._getSpeechForObjectAvailability(obj))
993 0
            utterances.extend(self._getSpeechForObjectAccelerator(obj))
994
995 0
        self._debugGenerator("_getSpeechForRadioMenuItem",
996 0
                             obj,
997 0
                             already_focused,
998 0
                             utterances)
999
1000 0
        return utterances
1001
1002 1
    def _getSpeechForRowHeader(self, obj, already_focused):
1003
        """Get the speech for a row header.
1004
1005
        Arguments:
1006
        - obj: the column header
1007
        - already_focused: False if object just received focus
1008
1009
        Returns a list of utterances to be spoken for the object.
1010
        """
1011
1012 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1013
1014 0
        self._debugGenerator("_getSpeechForRowHeader",
1015 0
                             obj,
1016 0
                             already_focused,
1017 0
                             utterances)
1018
1019 0
        return utterances
1020
1021 1
    def _getSpeechForScrollBar(self, obj, already_focused):
1022
        """Get the speech for a scroll bar.
1023
1024
        Arguments:
1025
        - obj: the scroll bar
1026
        - already_focused: False if object just received focus
1027
1028
        Returns a list of utterances to be spoken for the object.
1029
        """
1030
1031
        # [[[TODO: WDW - want to get orientation and maybe the
1032
        # percentage scrolled so far. Logged as bugzilla bug
1033
        # 319744.]]]
1034
        #
1035 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1036
1037 0
        self._debugGenerator("_getSpeechForScrollBar",
1038 0
                             obj,
1039 0
                             already_focused,
1040 0
                             utterances)
1041
1042 0
        return utterances
1043
1044 1
    def _getSpeechForSlider(self, obj, already_focused):
1045
        """Get the speech for a slider.  If the object already
1046
        had focus, just the value is spoken.
1047
1048
        Arguments:
1049
        - obj: the slider
1050
        - already_focused: False if object just received focus
1051
1052
        Returns a list of utterances to be spoken for the object.
1053
        """
1054
1055 0
        value = obj.value
1056
1057
        # OK, this craziness is all about trying to figure out the most
1058
        # meaningful formatting string for the floating point values.
1059
        # The number of places to the right of the decimal point should
1060
        # be set by the minimumIncrement, but the minimumIncrement isn't
1061
        # always set.  So...we'll default the minimumIncrement to 1/100
1062
        # of the range.  But, if max == min, then we'll just go for showing
1063
        # them off to two meaningful digits.
1064
        #
1065 0
        try:
1066 0
            minimumIncrement = value.minimumIncrement
1067 0
        except:
1068 0
            minimumIncrement = 0.0
1069
1070 0
        if minimumIncrement == 0.0:
1071 0
            minimumIncrement = (value.maximumValue - value.minimumValue) \
1072
                               / 100.0
1073
1074 0
        try:
1075 0
            decimalPlaces = max(0, -math.log10(minimumIncrement))
1076 0
        except:
1077 0
            try:
1078 0
                decimalPlaces = max(0, -math.log10(value.minimumValue))
1079 0
            except:
1080 0
                try:
1081 0
                    decimalPlaces = max(0, -math.log10(value.maximumValue))
1082 0
                except:
1083 0
                    decimalPlaces = 0
1084
1085 0
        formatter = "%%.%df" % decimalPlaces
1086 0
        valueString = formatter % value.currentValue
1087
        #minString   = formatter % value.minimumValue
1088
        #maxString   = formatter % value.maximumValue
1089
1090 0
        if already_focused:
1091 0
            utterances = [valueString]
1092
        else:
1093 0
            utterances = []
1094 0
            utterances.extend(self._getSpeechForObjectLabel(obj))
1095
1096
            # Ignore the text on the slider.  See bug 340559
1097
            # (http://bugzilla.gnome.org/show_bug.cgi?id=340559): the
1098
            # implementors of the slider support decided to put in a
1099
            # Unicode left-to-right character as part of the text,
1100
            # even though that is not painted on the screen.
1101
            #
1102
            # In Java, however, there are sliders without a label. In
1103
            # this case, we'll add to presentation the slider name if
1104
            # it exists and we haven't found anything yet.
1105
            #
1106 0
            if not utterances:
1107 0
                utterances.extend(self._getSpeechForObjectName(obj))
1108
1109 0
            utterances.extend(self._getSpeechForObjectRole(obj))
1110 0
            utterances.append(valueString)
1111 0
            utterances.extend(self._getSpeechForObjectAvailability(obj))
1112
1113 0
        self._debugGenerator("_getSpeechForSlider",
1114 0
                             obj,
1115 0
                             already_focused,
1116 0
                             utterances)
1117
1118 0
        return utterances
1119
1120 1
    def _getSpeechForSpinButton(self, obj, already_focused):
1121
        """Get the speech for a spin button.  If the object already has
1122
        focus, then only the new value is spoken.
1123
1124
        Arguments:
1125
        - obj: the spin button
1126
        - already_focused: False if object just received focus
1127
1128
        Returns a list of utterances to be spoken for the object.
1129
        """
1130
1131 4
        if already_focused:
1132 0
            utterances = [self._script.getDisplayedText(obj)]
1133
        else:
1134 4
            utterances = self._getDefaultSpeech(obj, already_focused)
1135
1136 4
        self._debugGenerator("_getSpeechForSpinButton",
1137 4
                             obj,
1138 4
                             already_focused,
1139 4
                             utterances)
1140
1141 4
        return utterances
1142
1143 1
    def _getSpeechForSplitPane(self, obj, already_focused):
1144
        """Get the speech for a split pane.
1145
1146
        Arguments:
1147
        - obj: the split pane
1148
        - already_focused: False if object just received focus
1149
1150
        Returns a list of utterances to be spoken for the object.
1151
        """
1152
1153 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1154
1155 0
        self._debugGenerator("_getSpeechForSplitPane",
1156 0
                             obj,
1157 0
                             already_focused,
1158 0
                             utterances)
1159
1160 0
        return utterances
1161
1162 1
    def _getSpeechForTable(self, obj, already_focused):
1163
        """Get the speech for a table
1164
1165
        Arguments:
1166
        - obj: the table
1167
        - already_focused: False if object just received focus
1168
1169
        Returns a list of utterances to be spoken for the object.
1170
        """
1171
1172 4
        utterances = self._getDefaultSpeech(obj, already_focused)
1173
1174 4
        self._debugGenerator("_getSpeechForTable",
1175 4
                             obj,
1176 4
                             already_focused,
1177 4
                             utterances)
1178
1179
        # If this is a table with no children, then let the user know.
1180
        #
1181 4
        hasItems = False
1182 4
        for i in range(0, obj.childCount):
1183 4
            child = obj.child(i)
1184 4
            if child.state.count(atspi.Accessibility.STATE_SHOWING):
1185 4
                hasItems = True
1186 4
                break
1187 4
        if not hasItems:
1188 0
            utterances.append(_("0 items"))
1189
1190 4
        return utterances
1191
1192 1
    def _getSpeechForTableCell(self, obj, already_focused):
1193
        """Get the speech utterances for a single table cell
1194
1195
        Arguments:
1196
        - obj: the table
1197
        - already_focused: False if object just received focus
1198
1199
        Returns a list of utterances to be spoken for the object.
1200
        """
1201
1202 253
        utterances = []
1203
1204
        # [[[TODO: WDW - Attempt to infer the cell type.  There's a
1205
        # bunch of stuff we can do here, such as check the EXPANDABLE
1206
        # state, check the NODE_CHILD_OF relation, etc.  Logged as
1207
        # bugzilla bug 319750.]]]
1208
        #
1209 253
        action = obj.action
1210 253
        if action:
1211 454
            for i in range(0, action.nActions):
1212 281
                debug.println(debug.LEVEL_FINEST,
1213 281
                    "speechgenerator.__getTableCellUtterances " \
1214
                    + "looking at action %d" % i)
1215 281
                if action.getName(i) == "toggle":
1216 73
                    obj.role = rolenames.ROLE_CHECK_BOX
1217 73
                    utterances = self._getSpeechForCheckBox(obj,
1218 73
                                                            already_focused)
1219 73
                    obj.role = rolenames.ROLE_TABLE_CELL
1220 73
                    break
1221
1222 253
        utterances.append(self._script.getDisplayedText(\
1223
                          self._script.getRealActiveDescendant(obj)))
1224
1225
        # [[[TODO: WDW - HACK attempt to determine if this is a node;
1226
        # if so, describe its state.]]]
1227
        #
1228 253
        if obj.state.count(atspi.Accessibility.STATE_EXPANDABLE):
1229 15
            if obj.state.count(atspi.Accessibility.STATE_EXPANDED):
1230 6
                utterances.append(_("expanded"))
1231
            else:
1232 9
                utterances.append(_("collapsed"))
1233
1234
            # If this is an expandable table cell with no children, then
1235
            # let the user know.
1236
            #
1237 15
            if obj.childCount == 0:
1238 15
                utterances.append(_("0 items"))
1239
1240 253
        self._debugGenerator("_getSpeechForTableCell",
1241 253
                             obj,
1242 253
                             already_focused,
1243 253
                             utterances)
1244
1245 253
        return utterances
1246
1247 1
    def _getSpeechForTableCellRow(self, obj, already_focused):
1248
        """Get the speech for a table cell row or a single table cell
1249
        if settings.readTableCellRow is False.
1250
1251
        Arguments:
1252
        - obj: the table
1253
        - already_focused: False if object just received focus
1254
1255
        Returns a list of utterances to be spoken for the object.
1256
        """
1257
1258 169
        utterances = []
1259
1260 169
        if (not already_focused):
1261 162
            if settings.readTableCellRow and obj.parent.table \
1262
                and (not self._script.isLayoutOnly(obj.parent)):
1263 162
                parent = obj.parent
1264 162
                row = parent.table.getRowAtIndex(obj.index)
1265 162
                column = parent.table.getColumnAtIndex(obj.index)
1266
1267
                # This is an indication of whether we should speak all the
1268
                # table cells (the user has moved focus up or down a row),
1269
                # or just the current one (focus has moved left or right in
1270
                # the same row).
1271
                #
1272 162
                speakAll = True
1273 162
                if parent.__dict__.has_key("lastRow") and \
1274
                    parent.__dict__.has_key("lastColumn"):
1275 151
                    speakAll = (parent.lastRow != row) or \
1276
                           ((row == 0 or row == parent.table.nRows-1) and \
1277
                            parent.lastColumn == column)
1278
1279 162
                if speakAll:
1280 317
                    for i in range(0, parent.table.nColumns):
1281 202
                        accRow = parent.table.getAccessibleAt(row, i)
1282 202
                        cell = atspi.Accessible.makeAccessible(accRow)
1283 202
                        showing = cell.state.count( \
1284
                                          atspi.Accessibility.STATE_SHOWING)
1285 202
                        if showing:
1286 199
                            utterances.extend(self._getSpeechForTableCell(cell,
1287 199
                                                           already_focused))
1288
                else:
1289 47
                    utterances.extend(self._getSpeechForTableCell(obj,
1290 47
                                                           already_focused))
1291
            else:
1292 0
                utterances = self._getSpeechForTableCell(obj, already_focused)
1293
        else:
1294 7
            utterances = self._getSpeechForTableCell(obj, already_focused)
1295
1296 169
        self._debugGenerator("_getSpeechForTableCellRow",
1297 169
                             obj,
1298 169
                             already_focused,
1299 169
                             utterances)
1300
1301 169
        return utterances
1302
1303 1
    def _getSpeechForTableColumnHeader(self, obj, already_focused):
1304
        """Get the speech for a table column header
1305
1306
        Arguments:
1307
        - obj: the table column header
1308
        - already_focused: False if object just received focus
1309
1310
        Returns a list of utterances to be spoken for the object.
1311
        """
1312
1313 21
        utterances = self._getSpeechForColumnHeader(obj, already_focused)
1314
1315 21
        self._debugGenerator("_getSpeechForTableColumnHeader",
1316 21
                             obj,
1317 21
                             already_focused,
1318 21
                             utterances)
1319
1320 21
        return utterances
1321
1322 1
    def _getSpeechForTableRowHeader(self, obj, already_focused):
1323
        """Get the speech for a table row header
1324
1325
        Arguments:
1326
        - obj: the table row header
1327
        - already_focused: False if object just received focus
1328
1329
        Returns a list of utterances to be spoken for the object.
1330
        """
1331
1332 0
        utterances = self._getSpeechForRowHeader(obj, already_focused)
1333
1334 0
        self._debugGenerator("_getSpeechForTableRowHeader",
1335 0
                             obj,
1336 0
                             already_focused,
1337 0
                             utterances)
1338
1339 0
        return utterances
1340
1341 1
    def _getSpeechForTearOffMenuItem(self, obj, already_focused):
1342
        """Get the speech for a tear off menu item
1343
1344
        Arguments:
1345
        - obj: the tear off menu item
1346
        - already_focused: False if object just received focus
1347
1348
        Returns a list of utterances to be spoken for the object.
1349
        """
1350
1351 0
        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
1352 0
            utterances = [_("tear off menu item")]
1353
        else:
1354 0
            utterances = [_("tear off")]
1355
1356 0
        self._debugGenerator("_getSpeechForTearOffMenuItem",
1357 0
                             obj,
1358 0
                             already_focused,
1359 0
                             utterances)
1360
1361 0
        return utterances
1362
1363 1
    def _getSpeechForTerminal(self, obj, already_focused):
1364
        """Get the speech for a terminal
1365
1366
        Arguments:
1367
        - obj: the terminal
1368
        - already_focused: False if object just received focus
1369
1370
        Returns a list of utterances to be spoken for the object.
1371
        """
1372
1373 9
        title = None
1374 9
        frame = self._script.getFrame(obj)
1375 9
        if frame:
1376 9
            title = frame.name
1377 9
        if not title:
1378 0
            title = self._script.getDisplayedLabel(obj)
1379
1380 9
        utterances = [title]
1381
1382 9
        self._debugGenerator("_getSpeechForTerminal",
1383 9
                             obj,
1384 9
                             already_focused,
1385 9
                             utterances)
1386
1387 9
        return utterances
1388
1389 1
    def _getSpeechForToggleButton(self, obj, already_focused):
1390
        """Get the speech for a toggle button.  If the toggle button already
1391
        had focus, then only the state is spoken.
1392
1393
        Arguments:
1394
        - obj: the check box
1395
        - already_focused: False if object just received focus
1396
1397
        Returns a list of utterances to be spoken for the object.
1398
        """
1399
1400 10
        utterances = []
1401 10
        if obj.state.count(atspi.Accessibility.STATE_CHECKED):
1402 2
            checkedState = _("pressed")
1403
        else:
1404 8
            checkedState = _("not pressed")
1405
1406
        # If it's not already focused, say it's name
1407
        #
1408 10
        if not already_focused:
1409 10
            label = self._getSpeechForObjectLabel(obj)
1410 10
            utterances.extend(label)
1411 10
            name = self._getSpeechForObjectName(obj)
1412 10
            if name != label:
1413 8
                utterances.extend(name)
1414 10
            utterances.extend(self._getSpeechForObjectRole(obj))
1415 10
            utterances.append(checkedState)
1416 10
            utterances.extend(self._getSpeechForObjectAvailability(obj))
1417
        else:
1418 0
            utterances.append(checkedState)
1419
1420 10
        self._debugGenerator("_getSpeechForToggleButton",
1421 10
                             obj,
1422 10
                             already_focused,
1423 10
                             utterances)
1424
1425 10
        return utterances
1426
1427 1
    def _getSpeechForToolBar(self, obj, already_focused):
1428
        """Get the speech for a tool bar
1429
1430
        Arguments:
1431
        - obj: the tool bar
1432
        - already_focused: False if object just received focus
1433
1434
        Returns a list of utterances to be spoken for the object.
1435
        """
1436
1437 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1438
1439 0
        self._debugGenerator("_getSpeechForToolBar",
1440 0
                             obj,
1441 0
                             already_focused,
1442 0
                             utterances)
1443
1444 0
        return utterances
1445
1446 1
    def _getSpeechForTree(self, obj, already_focused):
1447
        """Get the speech for a tree
1448
1449
        Arguments:
1450
        - obj: the tree
1451
        - already_focused: False if object just received focus
1452
1453
        Returns a list of utterances to be spoken for the object.
1454
        """
1455
1456 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1457
1458 0
        self._debugGenerator("_getSpeechForTree",
1459 0
                             obj,
1460 0
                             already_focused,
1461 0
                             utterances)
1462
1463 0
        return utterances
1464
1465 1
    def _getSpeechForTreeTable(self, obj, already_focused):
1466
        """Get the speech for a tree table
1467
1468
        Arguments:
1469
        - obj: the tree table
1470
        - already_focused: False if object just received focus
1471
1472
        Returns a list of utterances to be spoken for the object.
1473
        """
1474
1475 0
        utterances = self._getDefaultSpeech(obj, already_focused)
1476
1477 0
        self._debugGenerator("_getSpeechForTreeTable",
1478 0
                             obj,
1479 0
                             already_focused,
1480 0
                             utterances)
1481
1482 0
        return utterances
1483
1484 1
    def _getSpeechForWindow(self, obj, already_focused):
1485
        """Get the speech for a window
1486
1487
        Arguments:
1488
        - obj: the window
1489
        - already_focused: False if object just received focus
1490
1491
        Returns a list of utterances to be spoken for the object.
1492
        """
1493
1494 2
        utterances = self._getDefaultSpeech(obj, already_focused)
1495
1496 2
        self._debugGenerator("_getSpeechForWindow",
1497 2
                             obj,
1498 2
                             already_focused,
1499 2
                             utterances)
1500
1501 2
        return utterances
1502
1503 1
    def getSpeech(self, obj, already_focused):
1504
        """Get the speech for an Accessible object.  This will look
1505
        first to the specific speech generators and then to the
1506
        default speech generator.  This method is the primary method
1507
        that external callers of this class should use.
1508
1509
        Arguments:
1510
        - obj: the object
1511
        - already_focused: False if object just received focus
1512
1513
        Returns a list of utterances to be spoken.
1514
        """
1515
1516 799
        if self.speechGenerators.has_key(obj.role):
1517 792
            generator = self.speechGenerators[obj.role]
1518
        else:
1519 7
            generator = self._getDefaultSpeech
1520
1521 799
        return [" ".join(generator(obj, already_focused))]
1522
1523 1
    def getSpeechContext(self, obj, stopAncestor=None):
1524
        """Get the speech that describes the names and role of
1525
        the container hierarchy of the object, stopping at and
1526
        not including the stopAncestor.
1527
1528
        Arguments:
1529
        - obj: the object
1530
        - stopAncestor: the anscestor to stop at and not include (None
1531
          means include all ancestors)
1532
1533
        Returns a list of utterances to be spoken.
1534
        """
1535
1536 725
        utterances = []
1537
1538 725
        if not obj:
1539 0
            return utterances
1540
1541 725
        if obj is stopAncestor:
1542 15
            return utterances
1543
1544
        # We try to ignore fillers and panels without names.
1545
        # [[[TODO: WDW - HACK sometimes table cells can be children
1546
        # of table cells (see the "Browse" dialog of gnome-terminal
1547
        # via "Edit" -> "Current Profile" -> "General" Tab ->
1548
        # "Profile icon:" button -> "Browse..." button - each element
1549
        # in the list is a compound table cell where the icon and
1550
        # text are child table cells of the table cell).  So...
1551
        # we happily ignore those as well.  One thing we might
1552
        # want to do is treat the parent as a compound object.
1553
        # Logged as bugzilla bug 319751.]]]
1554
        #
1555 710
        parent = obj.parent
1556 710
        if parent \
1557
            and (obj.role == rolenames.ROLE_TABLE_CELL) \
1558
            and (parent.role == rolenames.ROLE_TABLE_CELL):
1559 0
            parent = parent.parent
1560
1561 1267
        while parent and (parent.parent != parent):
1562 1267
            if parent == stopAncestor:
1563 710
                break
1564 557
            if (parent.role != rolenames.ROLE_FILLER) \
1565
                and (parent.role != rolenames.ROLE_SECTION) \
1566
                and (parent.role != rolenames.ROLE_LAYERED_PANE) \
1567
                and (parent.role != rolenames.ROLE_SPLIT_PANE) \
1568
                and (parent.role != rolenames.ROLE_SCROLL_PANE) \
1569
                and (parent.role != rolenames.ROLE_UNKNOWN) \
1570
                and (not self._script.isLayoutOnly(parent)):
1571
1572
                # Announce the label and text of the object in the hierarchy.
1573
                #
1574 153
                text = self._script.getDisplayedText(parent)
1575 153
                label = self._script.getDisplayedLabel(parent)
1576
1577
                # Push announcement of cell after text and label.
1578
                #
1579 153
                if parent.role != rolenames.ROLE_TABLE_CELL:
1580 153
                    utterances.append(rolenames.getSpeechForRoleName(parent))
1581
1582 153
                if text and len(text):
1583 74
                    utterances.append(text)
1584 153
                if label and len(label):
1585 2
                    utterances.append(label)
1586
1587 153
                if parent.role == rolenames.ROLE_TABLE_CELL:
1588 0
                    utterances.append(rolenames.getSpeechForRoleName(parent))
1589
1590
            # [[[TODO: HACK - we've discovered oddness in hierarchies
1591
            # such as the gedit Edit->Preferences dialog.  In this
1592
            # dialog, we have labeled groupings of objects.  The
1593
            # grouping is done via a FILLER with two children - one
1594
            # child is the overall label, and the other is the
1595
            # container for the grouped objects.  When we detect this,
1596
            # we add the label to the overall context.]]]
1597
            #
1598 557
            if parent.role == rolenames.ROLE_FILLER:
1599 236
                label = self._script.getDisplayedLabel(parent)
1600 236
                if label and len (label):
1601 48
                    utterances.append(label)
1602
1603 557
            parent = parent.parent
1604
1605 710
        utterances.reverse()
1606
1607 710
        return utterances