def event_loseFocus(self):\r
self.stopMonitoring()\r
\r
+ class CandidateItem(NVDAObject):\r
+ \r
+ def getSymbolDescriptions(self,symbols):\r
+ descriptions=[]\r
+ numSymbols=len(symbols)\r
+ for symbol in symbols:\r
+ try:\r
+ symbolDescriptions=characterProcessing.getCharacterDescription(speech.getCurrentLanguage(),symbol) or []\r
+ except TypeError:\r
+ symbolDescriptions=[]\r
+ if numSymbols>1:\r
+ symbolDescriptions=symbolDescriptions[:1]\r
+ numSymbolDescriptions=len(symbolDescriptions)\r
+ for desc in symbolDescriptions:\r
+ if desc and desc[0]=='(' and desc[-1]==')':\r
+ desc=desc[1:-1]\r
+ elif numSymbolDescriptions==1:\r
+ # Translators: a human friendly message used as the description for an input composition candidate symbol when typing east-Asian characters, using both the symbol and its character description.\r
+ desc=_("{symbol} as in {description}").format(symbol=symbol,description=desc)\r
+ descriptions.append(desc)\r
+ if descriptions:\r
+ return ", ".join(descriptions)\r
+ \r
+ def reportFocus(self):\r
+ text=self.name\r
+ desc=self.description\r
+ if desc:\r
+ text+=u", "+desc\r
+ speech.speakText(text)\r
+ \r
+ def _get_visibleCandidateItemsText(self):\r
+ obj=self\r
+ textList=[]\r
+ while obj and isinstance(obj,CandidateItem) and controlTypes.STATE_INVISIBLE not in obj.states:\r
+ textList.append(obj.name)\r
+ obj=obj.previous\r
+ textList.reverse()\r
+ obj=self.next\r
+ while obj and isinstance(obj,CandidateItem) and controlTypes.STATE_INVISIBLE not in obj.states:\r
+ textList.append(obj.name)\r
+ obj=obj.next\r
+ self.visibleCandidateItemsText=", ".join(textList)\r
+ return self.visibleCandidateItemsText\r
++\r
+class RowWithFakeNavigation(NVDAObject):\r
+ """Provides table navigation commands for a row which doesn't support them natively.\r
+ The cells must be exposed as children and they must support the table cell properties.\r
+ """\r
+\r
+ _savedColumnNumber = None\r
+\r
+ def _moveToColumn(self, obj):\r
+ if not obj:\r
+ ui.message(_("edge of table"))\r
+ return\r
+ if obj is not self:\r
+ # Use the focused copy of the row as the parent for all cells to make comparison faster.\r
+ obj.parent = self\r
+ api.setNavigatorObject(obj)\r
+ speech.speakObject(obj, reason=controlTypes.REASON_FOCUS)\r
+\r
+ def _moveToColumnNumber(self, column):\r
+ child = column - 1\r
+ if child >= self.childCount:\r
+ return\r
+ cell = self.children[child]\r
+ self._moveToColumn(cell)\r
+\r
+ def script_moveToColumn(self, gesture):\r
+ self._moveToColumnNumber(int(gesture.mainKeyName[-1]))\r
+ # Translators: The description of an NVDA command.\r
+ script_moveToColumn.__doc__ = _("Moves the navigator object to the numbered column")\r
+\r
+ def script_moveToNextColumn(self, gesture):\r
+ cur = api.getNavigatorObject()\r
+ if cur == self:\r
+ new = self.firstChild\r
+ elif cur.parent != self:\r
+ new = self\r
+ else:\r
+ new = cur.next\r
+ self._moveToColumn(new)\r
+ script_moveToNextColumn.canPropagate = True\r
+ # Translators: The description of an NVDA command.\r
+ script_moveToNextColumn.__doc__ = _("Moves the navigator object to the next column")\r
+\r
+ def script_moveToPreviousColumn(self, gesture):\r
+ cur = api.getNavigatorObject()\r
+ if cur == self:\r
+ new = None\r
+ elif cur.parent != self or cur.columnNumber == 1:\r
+ new = self\r
+ else:\r
+ new = cur.previous\r
+ self._moveToColumn(new)\r
+ script_moveToPreviousColumn.canPropagate = True\r
+ # Translators: The description of an NVDA command.\r
+ script_moveToPreviousColumn.__doc__ = _("Moves the navigator object to the previous column")\r
+\r
+ def reportFocus(self):\r
+ col = self._savedColumnNumber\r
+ if not col:\r
+ return super(RowWithFakeNavigation, self).reportFocus()\r
+ self.__class__._savedColumnNumber = None\r
+ self._moveToColumnNumber(col)\r
+\r
+ def _moveToRow(self, row):\r
+ if not row:\r
+ return self._moveToColumn(None)\r
+ nav = api.getNavigatorObject()\r
+ if nav != self and nav.parent == self:\r
+ self.__class__._savedColumnNumber = nav.columnNumber\r
+ row.setFocus()\r
+\r
+ def script_moveToNextRow(self, gesture):\r
+ self._moveToRow(self.next)\r
+ script_moveToNextRow.canPropagate = True\r
+ # Translators: The description of an NVDA command.\r
+ script_moveToNextRow.__doc__ = _("Moves the navigator object and focus to the next row")\r
+\r
+ def script_moveToPreviousRow(self, gesture):\r
+ self._moveToRow(self.previous)\r
+ script_moveToPreviousRow.canPropagate = True\r
+ # Translators: The description of an NVDA command.\r
+ script_moveToPreviousRow.__doc__ = _("Moves the navigator object and focus to the previous row")\r
+\r
+ def initOverlayClass(self):\r
+ for n in xrange(1, 9):\r
+ self.bindGesture("kb:NVDA+control+%d" % n, "moveToColumn")\r
+\r
+ __gestures = {\r
+ "kb:control+alt+rightArrow": "moveToNextColumn",\r
+ "kb:control+alt+leftArrow": "moveToPreviousColumn",\r
+ "kb:control+alt+downArrow": "moveToNextRow",\r
+ "kb:control+alt+upArrow": "moveToPreviousRow",\r
+ }\r
+\r
+class RowWithoutCellObjects(NVDAObject):\r
+ """An abstract class which creates cell objects for table rows which don't natively expose them.\r
+ Subclasses must override L{_getColumnContent} and can optionally override L{_getColumnHeader}\r
+ to retrieve information about individual columns.\r
+ The parent (table) must support the L{columnCount} property.\r
+ """\r
+\r
+ def _get_childCount(self):\r
+ return self.parent.columnCount\r
+\r
+ def _getColumnContent(self, column):\r
+ """Get the text content for a given column of this row.\r
+ Subclasses must override this method.\r
+ @param column: The index of the column, starting at 1.\r
+ @type column: int\r
+ @rtype: str\r
+ """\r
+ raise NotImplementedError\r
+\r
+ def _getColumnHeader(self, column):\r
+ """Get the header text for this column.\r
+ @param column: The index of the column, starting at 1.\r
+ @type column: int\r
+ @rtype: str\r
+ """\r
+ raise NotImplementedError\r
+\r
+ def _makeCell(self, column):\r
+ if column == 0 or column > self.childCount:\r
+ return None\r
+ return _FakeTableCell(parent=self, column=column)\r
+\r
+ def _get_firstChild(self):\r
+ return self._makeCell(1)\r
+\r
+ def _get_children(self):\r
+ return [self._makeCell(column) for column in xrange(1, self.childCount + 1)]\r
+\r
+class _FakeTableCell(NVDAObject):\r
+\r
+ role = controlTypes.ROLE_TABLECELL\r
+\r
+ def __init__(self, parent=None, column=None):\r
+ super(_FakeTableCell, self).__init__()\r
+ self.parent = parent\r
+ self.columnNumber = column\r
+ try:\r
+ self.rowNumber = self.parent.positionInfo["indexInGroup"]\r
+ except KeyError:\r
+ pass\r
+ self.processID = parent.processID\r
+ try:\r
+ # HACK: Some NVDA code depends on windowHandle and windowClassName, even for non-Window objects.\r
+ self.windowHandle = parent.windowHandle\r
+ self.windowClassName = parent.windowClassName\r
+ except AttributeError:\r
+ pass\r
+\r
+ def _get_next(self):\r
+ return self.parent._makeCell(self.columnNumber + 1)\r
+\r
+ def _get_previous(self):\r
+ return self.parent._makeCell(self.columnNumber - 1)\r
+\r
+ firstChild = None\r
+\r
+ def _get_name(self):\r
+ return self.parent._getColumnContent(self.columnNumber)\r
+\r
+ def _get_columnHeaderText(self):\r
+ return self.parent._getColumnHeader(self.columnNumber)\r
+\r
+ def _get_tableID(self):\r
+ return id(self.parent.parent)\r
+\r
+ def _get_states(self):\r
+ return self.parent.states\r