46
47
("Fr-Ca-g2.ctb", _("French (Canada) grade 2")),
47
48
("fr-bfu-comp6.utb", _("French (unified) 6 dot computer braille")),
48
49
("fr-bfu-comp8.utb", _("French (unified) 8 dot computer braille")),
49
("fr-bfu-g2.ctb", _("French (unified) Grade 2")), ("gr-gr-g1.utb", _("Greek (Greece) grade 1")),
50
("fr-bfu-g2.ctb", _("French (unified) Grade 2")),
51
("gr-gr-g1.utb", _("Greek (Greece) grade 1")),
52
("gez-g1.ctb", _("Ethiopic grade 1")),
50
53
("he.ctb", _("Hebrew 8 dot computer braille")),
51
54
("hi-in-g1.utb", _("Hindi grade 1")),
52
55
("hr.ctb", _("Croatian 8 dot computer braille")),
55
58
("Lv-Lv-g1.utb", _("Latvian grade 1")),
56
59
("nl-be-g1.utb", _("Dutch (Belgium) grade 1")),
57
60
("Nl-Nl-g1.utb", _("Dutch (netherlands) grade 1")),
61
("no-no.ctb", _("Norwegian 8 dot computer braille")),
58
62
("No-No-g0.utb", _("Norwegian grade 0")),
59
63
("No-No-g1.ctb", _("Norwegian grade 1")),
60
64
("No-No-g2.ctb", _("Norwegian grade 2")),
64
68
("ru-ru-g1.utb", _("Russian grade 1")),
65
69
("Se-Se-g1.utb", _("Swedish grade 1")),
66
70
("sk-sk-g1.utb", _("Slovak")),
71
("sl-si-g1.utb", _("Slovene grade 1")),
72
("sr-g1.ctb", _("Serbian grade 1")),
73
("tr.ctb", _("Turkish grade 1")),
67
74
("UEBC-g1.utb", _("Unified English Braille Code grade 1")),
68
75
("UEBC-g2.ctb", _("Unified English Braille Code grade 2")),
69
76
("zh-hk.ctb", _("Chinese (Hong Kong, Cantonese)")),
70
77
("zh-tw.ctb", _("Chinese (Taiwan, Mandarin)")),
78
# ("nvdajp.ctb", _("Japanese by NVDAJP")),
88
96
positiveStateLabels = {
97
# Translators: Displayed in braille when an object (e.g. a check box) is checked.
89
98
controlTypes.STATE_CHECKED: _("(x)"),
99
# Translators: Displayed in braille when an object (e.g. a check box) is half checked.
100
controlTypes.STATE_HALFCHECKED: _("(-)"),
101
# Translators: Displayed in braille when an object is selected.
90
102
controlTypes.STATE_SELECTED: _("sel"),
103
# Translators: Displayed in braille when an object has a popup (usually a sub-menu).
91
104
controlTypes.STATE_HASPOPUP: _("submnu"),
105
# Translators: Displayed in braille when an object supports autocompletion.
106
controlTypes.STATE_AUTOCOMPLETE: _("..."),
107
# Translators: Displayed in braille when an object (e.g. a tree view item) is expanded.
108
controlTypes.STATE_EXPANDED: _("-"),
109
# Translators: Displayed in braille when an object (e.g. a tree view item) is collapsed.
110
controlTypes.STATE_COLLAPSED: _("+"),
111
# Translators: Displayed in braille when an object (e.g. an editable text field) is read-only.
112
controlTypes.STATE_READONLY: _("ro"),
93
114
negativeStateLabels = {
115
# Translators: Displayed in braille when an object (e.g. a check box) is not checked.
94
116
controlTypes.STATE_CHECKED: _("( )"),
119
def NVDAObjectHasUsefulText(obj):
121
return issubclass(obj.TextInfo,displayModel.DisplayModelTextInfo) or obj.role in (controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_TERMINAL) or controlTypes.STATE_EDITABLE in obj.states
97
123
def _getDisplayDriver(name):
98
124
return __import__("brailleDisplayDrivers.%s" % name, globals(), locals(), ("brailleDisplayDrivers",)).BrailleDisplayDriver
154
180
if config.conf["braille"]["expandAtCursor"] and self.cursorPos is not None:
155
181
mode |= louis.compbrlAtCursor
156
182
text=unicode(self.rawText).replace('\0','')
157
braille, self.brailleToRawPos, self.rawToBraillePos, brailleCursorPos = louis.translate([os.path.join(TABLES_DIR, config.conf["braille"]["translationTable"])], text, mode=mode, cursorPos=self.cursorPos or 0)
184
#if config.conf["braille"]["translationTable"] == 'nvdajp.ctb':
185
# from nvdajptext import Wakach
186
# text=Wakach.japanese_braille_translate(text)
188
braille, self.brailleToRawPos, self.rawToBraillePos, brailleCursorPos = louis.translate(
189
[os.path.join(TABLES_DIR, config.conf["braille"]["translationTable"]),
190
"braille-patterns.cti"],
191
text, mode=mode, cursorPos=self.cursorPos or 0)
158
192
# liblouis gives us back a character string of cells, so convert it to a list of ints.
159
193
# For some reason, the highest bit is set, so only grab the lower 8 bits.
160
194
self.brailleCells = [ord(cell) & 255 for cell in braille]
228
261
keyboardShortcut = propertyValues.get("keyboardShortcut")
229
262
if keyboardShortcut:
230
263
textList.append(keyboardShortcut)
231
positionInfo = propertyValues["positionInfo"]
264
positionInfo = propertyValues.get("positionInfo")
233
if 'indexInGroup' in positionInfo and 'similarItemsInGroup' in positionInfo:
234
textList.append(_("%s of %s")%(positionInfo['indexInGroup'],positionInfo['similarItemsInGroup']))
235
if 'level' in positionInfo:
236
textList.append(_('level %s')%positionInfo['level'])
266
indexInGroup = positionInfo.get("indexInGroup")
267
similarItemsInGroup = positionInfo.get("similarItemsInGroup")
268
if indexInGroup and similarItemsInGroup:
269
textList.append(_("%s of %s") % (indexInGroup, similarItemsInGroup))
270
level = positionInfo.get("level")
271
if level is not None:
272
# Translators: Displayed in braille when an object (e.g. a tree view item) has a hierarchical level.
273
# %s is replaced with the level.
274
textList.append(_('lv %s')%positionInfo['level'])
237
275
return " ".join([x for x in textList if x])
239
277
class NVDAObjectRegion(Region):
430
468
return region, bufferPos - start
431
469
raise LookupError("No such position")
433
def regionPosToBufferPos(self, region, pos):
471
def regionPosToBufferPos(self, region, pos, allowNearest=False):
434
472
for testRegion, start, end in self.regionsWithPositions:
435
473
if region == testRegion:
474
if pos < end - start:
475
# The requested position is still valid within the region.
437
476
return start + pos
478
# The position within the region isn't valid,
479
# but the region is valid, so return its start.
483
# Resort to the start of the last region.
438
485
raise LookupError("No such position")
440
487
def bufferPosToWindowPos(self, bufferPos):
552
599
self._savedWindow = self.bufferPosToRegionPos(self.windowStartPos)
554
def restoreWindow(self, ignoreErrors=False):
601
def restoreWindow(self):
555
602
"""Restore the window saved by L{saveWindow}.
556
@param ignoreErrors: Whether to ignore errors.
557
@type ignoreErrors: bool
558
603
@precondition: L{saveWindow} has been called.
559
604
@postcondition: If the saved position is valid, the window is restored.
560
@raise LookupError: If C{ignoreErrors} is C{False} and the saved region position is invalid.
605
Otherwise, the nearest position is restored.
563
self.windowStartPos = self.regionPosToBufferPos(*self._savedWindow)
607
region, pos = self._savedWindow
608
self.windowStartPos = self.regionPosToBufferPos(region, pos, allowNearest=True)
568
610
_cachedFocusAncestorsEnd = 0
569
611
def invalidateCachedFocusAncestors(index):
635
677
def getFocusRegions(obj, review=False):
636
678
# Late import to avoid circular import.
637
from virtualBuffers import VirtualBuffer
679
from treeInterceptorHandler import TreeInterceptor
638
680
from cursorManager import CursorManager
639
681
if isinstance(obj, CursorManager):
640
682
region2 = (ReviewTextInfoRegion if review else CursorManagerRegion)(obj)
641
elif (obj.role in (controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_TERMINAL) or controlTypes.STATE_EDITABLE in obj.states):
683
elif isinstance(obj, TreeInterceptor) or NVDAObjectHasUsefulText(obj):
642
684
region2 = (ReviewTextInfoRegion if review else TextInfoRegion)(obj)
645
if isinstance(obj, VirtualBuffer):
687
if isinstance(obj, TreeInterceptor):
646
688
obj = obj.rootNVDAObject
647
689
region = (ReviewNVDAObjectRegion if review else NVDAObjectRegion)(obj, appendText=" " if region2 else "")
662
706
self.messageBuffer = BrailleBuffer(self)
663
707
self._messageCallLater = None
664
708
self.buffer = self.mainBuffer
665
#config.conf["braille"]["tetherTo"] = self.TETHER_FOCUS
666
709
#: Whether braille is enabled.
668
711
self.enabled = False
669
self._keyCounterForLastMessage=0
712
self._keyCountForLastMessage=0
713
self._cursorPos = None
714
self._cursorBlinkUp = True
716
self._cursorBlinkTimer = None
719
if self._messageCallLater:
720
self._messageCallLater.Stop()
721
self._messageCallLater = None
722
if self._cursorBlinkTimer:
723
self._cursorBlinkTimer.Stop()
724
self._cursorBlinkTimer = None
726
self.display.terminate()
671
729
def _get_tether(self):
672
730
return config.conf["braille"]["tetherTo"]
697
755
newDisplay = newDisplay()
699
self.display.terminate()
758
self.display.terminate()
760
log.error("Error terminating previous display driver", exc_info=True)
700
761
self.display = newDisplay
701
762
self.displaySize = newDisplay.numCells
702
763
self.enabled = bool(self.displaySize)
703
764
config.conf["braille"]["display"] = name
704
765
log.info("Loaded braille display driver %s" % name)
708
768
log.error("Error initializing display driver", exc_info=True)
709
769
self.setDisplayByName("noBraille")
712
def configDisplay(self):
713
"""Configure the braille display driver based on the user's configuration.
714
@precondition: L{display} has been set.
716
self.display.cursorBlinkRate = config.conf["braille"]["cursorBlinkRate"]
717
self.display.cursorShape = 0xc0
772
def _updateDisplay(self):
773
if self._cursorBlinkTimer:
774
self._cursorBlinkTimer.Stop()
775
self._cursorBlinkTimer = None
776
self._cursorBlinkUp = True
777
self._displayWithCursor()
778
blinkRate = config.conf["braille"]["cursorBlinkRate"]
779
if blinkRate and self._cursorPos is not None:
780
self._cursorBlinkTimer = wx.PyTimer(self._blink)
781
self._cursorBlinkTimer.Start(blinkRate)
783
def _displayWithCursor(self):
786
cells = list(self._cells)
787
if self._cursorPos is not None and self._cursorBlinkUp:
788
cells[self._cursorPos] |= self.cursorShape
789
self.display.display(cells)
792
self._cursorBlinkUp = not self._cursorBlinkUp
793
self._displayWithCursor()
719
795
def update(self):
720
self.display.display(self.buffer.windowBrailleCells)
721
self.display.cursorPos = self.buffer.cursorWindowPos
796
cells = self.buffer.windowBrailleCells
797
# cells might not be the full length of the display.
798
# Therefore, pad it with spaces to fill the display.
799
self._cells = cells + [0] * (self.displaySize - len(cells))
800
self._cursorPos = self.buffer.cursorWindowPos
801
self._updateDisplay()
723
803
def scrollForward(self):
724
804
self.buffer.scrollForward()
917
1013
@param cells: The braille cells to display.
918
1014
@type cells: [int, ...]
922
def _get_cursorPos(self):
925
def _set_cursorPos(self, pos):
928
def _get_cursorShape(self):
931
def _set_cursorShape(self, shape):
934
def _get_cursorBlinkRate(self):
937
def _set_cursorBlinkRate(self, rate):
940
class BrailleDisplayDriverWithCursor(BrailleDisplayDriver):
941
"""Abstract base braille display driver which manages its own cursor.
942
This should be used by braille display drivers where the display or underlying driver does not provide support for a cursor.
943
Instead of overriding L{display}, subclasses should override L{_display}.
1017
#: Global input gesture map for this display driver.
1018
#: @type: L{inputCore.GlobalGestureMap}
1021
class BrailleDisplayGesture(inputCore.InputGesture):
1022
"""A button, wheel or other control pressed on a braille display.
1023
Subclasses must provide L{source} and L{id}.
1024
L{routingIndex} should be provided for routing buttons.
1025
If the braille display driver is a L{baseObject.ScriptableObject}, it can provide scripts specific to input gestures from this display.
947
self._cursorPos = None
948
self._cursorBlinkRate = 0
949
self._cursorBlinkUp = True
950
self._cursorShape = 0
952
self._cursorBlinkTimer = None
955
def _initCursor(self):
956
if self._cursorBlinkTimer:
957
self._cursorBlinkTimer.Stop()
958
self._cursorBlinkTimer = None
959
self._cursorBlinkUp = True
960
self._displayWithCursor()
961
if self._cursorBlinkRate and self._cursorPos is not None:
962
self._cursorBlinkTimer = wx.PyTimer(self._blink)
963
self._cursorBlinkTimer.Start(self._cursorBlinkRate)
966
self._cursorBlinkUp = not self._cursorBlinkUp
967
self._displayWithCursor()
969
def _get_cursorPos(self):
970
return self._cursorPos
972
def _set_cursorPos(self, pos):
973
self._cursorPos = pos
976
def _get_cursorBlinkRate(self):
977
return self._cursorBlinkRate
979
def _set_cursorBlinkRate(self, rate):
980
self._cursorBlinkRate = rate
983
def _get_cursorShape(self):
984
return self._cursorShape
986
def _set_cursorShape(self, shape):
987
self._cursorShape = shape
990
def display(self, cells):
991
# cells might not be the full length of the display.
992
# Therefore, pad it with spaces to fill the display so that the cursor can lie beyond it.
993
self._cells = cells + [0] * (self.numCells - len(cells))
994
self._displayWithCursor()
996
def _displayWithCursor(self):
999
cells = list(self._cells)
1000
if self._cursorPos is not None and self._cursorBlinkUp:
1001
cells[self._cursorPos] |= self._cursorShape
1002
self._display(cells)
1004
def _display(self, cells):
1005
"""Actually display the given cells to the display.
1006
L{display} calls methods to handle the cursor representation as appropriate.
1007
However, this method (L{_display}) is called to actually display the final cells.
1028
def _get_source(self):
1029
"""The string used to identify all gestures from this display.
1030
This should generally be the driver name.
1031
This string will be included in the source portion of gesture identifiers.
1032
For example, if this was C{alvaBC6},
1033
a display specific gesture identifier might be C{br(alvaBC6):etouch1}.
1036
raise NotImplementedError
1039
"""The unique, display specific id for this gesture.
1042
raise NotImplementedError
1044
#: The index of the routing key or C{None} if this is not a routing key.
1048
def _get_identifiers(self):
1049
return (u"br({source}):{id}".format(source=self.source, id=self.id).lower(),)
1051
def _get_displayName(self):
1054
def _get_scriptableObject(self):
1055
display = handler.display
1056
if isinstance(display, baseObject.ScriptableObject):
1058
return super(BrailleDisplayGesture, self).scriptableObject