[orca] Improve presentation of editable comboboxes
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Improve presentation of editable comboboxes
- Date: Mon, 17 Oct 2016 09:20:21 +0000 (UTC)
commit 41707bc0c8f931f45856a34cbc57bc335a5bbdf1
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Mon Oct 17 05:19:38 2016 -0400
Improve presentation of editable comboboxes
src/orca/formatting.py | 4 +-
src/orca/script_utilities.py | 38 ++++++++++++-
src/orca/scripts/apps/soffice/script.py | 7 ++-
src/orca/scripts/apps/soffice/speech_generator.py | 60 +++++++++++++++------
src/orca/speech_generator.py | 3 +
5 files changed, 89 insertions(+), 23 deletions(-)
---
diff --git a/src/orca/formatting.py b/src/orca/formatting.py
index e671795..30e6770 100644
--- a/src/orca/formatting.py
+++ b/src/orca/formatting.py
@@ -154,8 +154,8 @@ formatting = {
},
pyatspi.ROLE_COMBO_BOX: {
'focused': 'expandableState',
- 'unfocused': 'labelAndName + roleName + pause + positionInList + ' + MNEMONIC + ' + accelerator',
- 'basicWhereAmI': 'label + roleName + pause + name + positionInList + ' + MNEMONIC + ' +
accelerator'
+ 'unfocused': 'labelAndName + roleName + pause + (currentLineText + anyTextSelection or
positionInList) + ' + MNEMONIC + ' + accelerator',
+ 'basicWhereAmI': 'label + roleName + pause + name + (currentLineText + anyTextSelection or
positionInList) + ' + MNEMONIC + ' + accelerator'
},
pyatspi.ROLE_DIAL: {
'focused': 'value',
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 789f9fe..529df0b 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -3329,11 +3329,45 @@ class Utilities:
def isEntryCompletionPopupItem(self, obj):
return False
+ def getEntryForEditableComboBox(self, obj):
+ if not obj:
+ return None
+
+ try:
+ role = obj.getRole()
+ except:
+ msg = "ERROR: Exception getting role for %s" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ return None
+
+ if role != pyatspi.ROLE_COMBO_BOX:
+ return None
+
+ children = [x for x in obj if self.isEditableTextArea(x)]
+ if len(children) == 1:
+ return children[0]
+
+ return None
+
def isEditableComboBox(self, obj):
- return False
+ return self.getEntryForEditableComboBox(obj) is not None
def isEditableDescendantOfComboBox(self, obj):
- return False
+ if not obj:
+ return False
+
+ try:
+ state = obj.getState()
+ except:
+ msg = "ERROR: Exception getting state for %s" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ return False
+
+ if not state.contains(pyatspi.STATE_EDITABLE):
+ return False
+
+ isComboBox = lambda x: x and x.getRole() == pyatspi.ROLE_COMBO_BOX
+ return pyatspi.findAncestor(obj, isComboBox) is not None
def isPopOver(self, obj):
return False
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index fda59c0..e2f3acd 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -698,14 +698,15 @@ class Script(default.Script):
orca.setLocusOfFocus(event, event.source)
return
- if self.utilities.isZombie(event.source):
+ role = event.source.getRole()
+
+ if self.utilities.isZombie(event.source) \
+ or role in [pyatspi.ROLE_TEXT, pyatspi.ROLE_LIST]:
comboBox = self.utilities.containingComboBox(event.source)
if comboBox:
orca.setLocusOfFocus(event, comboBox, True)
return
- role = event.source.getRole()
-
# This seems to be something we inherit from Gtk+
if role in [pyatspi.ROLE_TEXT, pyatspi.ROLE_PASSWORD_TEXT]:
orca.setLocusOfFocus(event, event.source)
diff --git a/src/orca/scripts/apps/soffice/speech_generator.py
b/src/orca/scripts/apps/soffice/speech_generator.py
index 88e6231..4667dff 100644
--- a/src/orca/scripts/apps/soffice/speech_generator.py
+++ b/src/orca/scripts/apps/soffice/speech_generator.py
@@ -111,29 +111,44 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
object will be used. This method will return an empty array
if nothing can be found.
"""
- role = args.get('role', obj.getRole())
- if role == pyatspi.ROLE_TEXT and obj.parent.getRole() == pyatspi.ROLE_COMBO_BOX:
- return []
- if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
- and self._script.utilities.ancestorWithRole(
- obj, [pyatspi.ROLE_TOOL_BAR], [pyatspi.ROLE_FRAME]):
- acss = self.voice(speech_generator.SYSTEM)
+ # TODO - JD: This should be the behavior by default. But the default
+ # generators call displayedText(). Once that is corrected, this method
+ # can be removed.
+ if obj.name:
result = [obj.name]
- if result:
- result.extend(acss)
- return result
+ result.extend(self.voice(speech_generator.DEFAULT))
+ return result
- return speech_generator.SpeechGenerator._generateName(
- self, obj, **args)
+ return super()._generateName(obj, **args)
+
+ def _generateLabelAndName(self, obj, **args):
+ if obj.getRole() != pyatspi.ROLE_COMBO_BOX:
+ return super()._generateLabelAndName(obj, **args)
+
+ # TODO - JD: This should be the behavior by default because many
+ # toolkits use the label for the name.
+ result = []
+ label = self._script.utilities.displayedLabel(obj)
+ if label:
+ result.append(label)
+ result.extend(self.voice(speech_generator.DEFAULT))
+
+ name = obj.name
+ if label == name or not name:
+ selected = self._script.utilities.selectedChildren(obj)
+ if selected:
+ name = selected[0].name
+
+ if name:
+ result.append(name)
+ result.extend(self.voice(speech_generator.DEFAULT))
+
+ return result
def _generateLabelOrName(self, obj, **args):
"""Gets the label or the name if the label is not preset."""
- role = args.get('role', obj.getRole())
- if role == pyatspi.ROLE_TEXT and obj.parent.getRole() == pyatspi.ROLE_COMBO_BOX:
- return []
-
result = []
acss = self.voice(speech_generator.DEFAULT)
override = self.__overrideParagraph(obj, **args)
@@ -162,6 +177,13 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
self, obj, **args))
return result
+ def _generateAnyTextSelection(self, obj, **args):
+ comboBoxEntry = self._script.utilities.getEntryForEditableComboBox(obj)
+ if comboBoxEntry:
+ return super()._generateAnyTextSelection(comboBoxEntry)
+
+ return super()._generateAnyTextSelection(obj, **args)
+
def _generateAvailability(self, obj, **args):
"""Returns an array of strings for use by speech and braille that
represent the grayed/sensitivity/availability state of the
@@ -214,6 +236,12 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
if priorObj and priorObj.parent != obj.parent:
return []
+ if obj.getRole() == pyatspi.ROLE_COMBO_BOX:
+ entry = self._script.utilities.getEntryForEditableComboBox(obj)
+ if entry:
+ return super()._generateCurrentLineText(entry)
+ return []
+
# TODO - JD: The SayLine, etc. code should be generated and not put
# together in the scripts. In addition, the voice crap needs to go
# here. Then it needs to be removed from the scripts.
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index 3f01895..a019261 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -1654,6 +1654,9 @@ class SpeechGenerator(generator.Generator):
and obj.parent == self._script.utilities.topLevelObject(obj):
return []
+ if self._script.utilities.isEditableComboBox(obj):
+ return []
+
result = []
acss = self.voice(SYSTEM)
position, total = self._script.utilities.getPositionAndSetSize(obj)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]