Repository: nvaccess/nvda

Issue:
Improve support for Eclipse
Hi,

I made some modifications to the AppModule for the Eclipse IDE.

It's to allow using the autocompletion feature without leaving the focus from the code editor.

[eclipse_appModule_patch.txt](https://github.com/nvaccess/nvda/files/85156/eclipse_appModule_patch.txt)

It's a patch file.

Cheers.



Discussion:
```
+class autocompletionItem(IAccessible):
```

Following code semantics, the class should probably be called AutocompletionItem (with capital A).

```
+       # Fixme: I don't know if it is the correct way to do this.
+       ui.message(self.name)
```

With default configuration this will show the message in braille for only a few seconds. If I remember correctly Eclipse doesn't pop up a proper context menu for these suggestions, so this solution may be the next best thing. Still, if it is actually a list that stays on screen for the programmer to ponder over it'd be nice if NVDA could interpret it as such. Would it not be possible to auto-focus this thing when it appears? Just some uneducated guesses...

Hello,

El 13/01/2016 a las 07:23 a.m., Davy Kager escribió:

> ```
> +class autocompletionItem(IAccessible):
> ```
> 
> Following code semantics, the class should probably be called
> AutocompletionItem (with capital A).

Yes, I did read the code semantics after posting it.

> ```
>   * # Fixme: I don't know if it is the correct way to do this.
>   * ui.message(self.name)
> ```
> 
> With default configuration this will show the message in braille for
> only a few seconds. If I remember correctly Eclipse doesn't pop up a
> proper context menu for these suggestions, so this solution may be the
> next best thing. Still, if it is actually a list that stays on screen
> for the programmer to ponder over it'd be nice if NVDA could interpret
> it as such. Would it not be possible to auto-focus this thing when it
> appears? Just some uneducated guesses...

Anyway, I noticed some problems dealing with it in this way. For 
example, if you are at a longer line, you need to wait the synthesizer 
finish reading it before start reading the selected suggestion.

Additionally, this script actually doesn't support the XML 
Autocompleter, for example.

I think that it can be better sending a fake gainFocus event or stopping 
the speech before it can be read.

I'll test these alternatives and then I'll post a pull request.

P.D: Sorry, my English is too bad.

## Cheers,

¡Cuando tus fuerzas terminan, las de Dios comienzan!

Hello,

I believe that it's solved. Please test it and reopen this isswe if you have problems.

Cheers,

Hi,
Please don't close an issue just because you think it is closed (this patch requires further user testing).
An issue should be closed if:
1. This is a duplicate of an existing issue.
2. A setting change has fixed na issue.
3. Officially included in a release version of NVDA (inclusion into master means it is definitely included in the next version).
If ther's a way to reopen this...
Thanks.

The change associated with issue has been reverted. Re-opening this issue. The change caused an error to be raised in some circumstances please see https://github.com/nvaccess/nvda/pull/5680#issuecomment-340877036 for further details.
are there any further alternatives planed to solve this issue? @feerrenrut mybe we can get some further suggestions from @albzan who created an eclipse addon? @albzan are you planning to raise any pull requests with improvements?
Hello,

I'm tweaking this a little...

Sorry for the *huge* delay.

Resolving patch:
diff --git a/source/appModules/eclipse.py b/source/appModules/eclipse.py
--- a/source/appModules/eclipse.py
+++ b/source/appModules/eclipse.py
@@ -7,8 +7,22 @@
 import controlTypes
 import appModuleHandler
 from NVDAObjects.IAccessible import IAccessible
+from NVDAObjects.behaviors import EditableTextWithSuggestions
+import speech
+import braille
+import ui
+import api
+import sayAllHandler
+import eventHandler
+import keyboardHandler
+from scriptHandler import script
 
-class EclipseTextArea(IAccessible):
+class EclipseTextArea(EditableTextWithSuggestions, IAccessible):
+
+	def event_suggestionsClosed(self):
+		super(EclipseTextArea, self).event_suggestionsClosed()
+		self.appModule.selectedItem = None
+		self.appModule.selectedItemName = None
 
 	def event_valueChange(self):
 		# #2314: Eclipse incorrectly fires valueChange when the selection changes.
@@ -17,7 +31,134 @@ def event_valueChange(self):
 		# Therefore, just drop this event.
 		pass
 
+	def event_caret(self):
+		super(EclipseTextArea, self).event_caret()
+
+		# Check suggestion item and close the list if it is not valid
+		try:
+			if self.appModule.selectedItem and not self.appModule.selectedItem.name:
+				self.event_suggestionsClosed()
+		except:
+			pass
+
+	@script(
+		gestures = ["kb:enter", "kb:escape"]
+	)
+	def script_closeAutocompleter(self, gesture):
+		gesture.send()
+
+		# Close the suggestions list if it is opened
+		if self.appModule.selectedItem:
+			self.event_suggestionsClosed()
+
+	@script(
+		# Translators: Input help mode message for the 'read documentation script
+		description = _("Tries to read documentation for the selected autocompletion item."),
+		gesture = "kb:nvda+d"
+	)
+	def script_readDocumentation(self, gesture):
+		rootDocumentationWindow = None
+
+		# If there aren't any suggestion selected, there is no way to find quick documentation
+		if not self.appModule.selectedItem:
+			gesture.send()
+			return
+
+		# Try to locate the documentation document
+		try:
+			rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous.previous
+		except AttributeError:
+			pass
+
+		# In XML documents this is different, maybe in other editors too
+		# so we try to locate the root window again
+		if not rootDocumentationWindow or not rootDocumentationWindow.appModule == self.appModule:
+			try:
+				rootDocumentationWindow = self.appModule.selectedItem.parent.parent.parent.parent.previous
+			except AttributeError:
+				pass
+
+		# Check if this object is from the same appModule
+		if rootDocumentationWindow and rootDocumentationWindow.appModule == self.appModule:
+			api.setNavigatorObject(rootDocumentationWindow)
+			
+			documentObj = rootDocumentationWindow
+
+			while documentObj:
+				if documentObj.firstChild:
+					documentObj = documentObj.firstChild
+
+					# In some editors the help document is a HTML ones
+					# On XML documents, for example, it is a simple read-only editable text
+					if documentObj.role in (controlTypes.ROLE_DOCUMENT, controlTypes.ROLE_EDITABLETEXT):
+						break
+				else:
+					break
+
+			if documentObj.role == controlTypes.ROLE_DOCUMENT:
+				api.setNavigatorObject(documentObj)
+				braille.handler.handleReviewMove()
+				sayAllHandler.readText(sayAllHandler.CURSOR_REVIEW)
+
+			elif documentObj.role == controlTypes.ROLE_EDITABLETEXT:
+				ui.message(documentObj.value)
+
+		else:
+			# Translators: When the help popup cannot be found for the selected autocompletion item
+			ui.message(_("Cann't find the documentation window."))
+
+	@script(
+		gesture="kb:tab"
+	)
+	def script_completeInstruction(self, gesture):
+		"""
+		Performs a standard autocompletion with the `TAB` key, like in other editors.
+		"""
+
+		# We need to ensure that the autocompletion popup is open
+		if self.appModule.selectedItem:
+			self.script_closeAutocompleter(keyboardHandler.KeyboardInputGesture.fromName("enter"))
+			return
+
+		# If not, we send the 'tab' key as is
+		gesture.send()
+
+class AutocompletionListItem(IAccessible):
+
+	def event_selection(self):
+		if not self.appModule.selectedItem:
+			api.getFocusObject().event_suggestionsOpened()
+
+		# This is to ease finding the elp document
+		if self.appModule.selectedItem != self:
+			self.appModule.selectedItem = self
+
+		# If autocompletion popup is open and you write some text in the
+		# document, the selection event is not fired. For some reason, neither
+		# nameChange, so we need this check:
+		if self.appModule.selectedItemName != self.name:
+			self.appModule.selectedItemName = self.name
+			speech.cancelSpeech()
+
+			# Reporting as focused should be sufficient
+			self.reportFocus()
+
+			# I picked up this from UIA SuggestionItem for rendering in braille.
+			# Simply calling `reportFocus` doesn't outputs the text to braille devices
+			# and reporting with `ui.message` needs an extra translation string when reporting position info
+			braille.handler.message(
+				braille.getBrailleTextForProperties(name=self.name,
+					role=self.role, position=self.positionInfo))
+
 class AppModule(appModuleHandler.AppModule):
+	LIST_VIEW_CLASS = "SysListView32"
+
+	# Item and name
+	selectedItem = None
+	selectedItemName = None
+
+	def __init__(self,processID,appName=None):
+		super(AppModule,self).__init__(processID,appName)
 
 	def event_NVDAObject_init(self, obj):
 		if obj.windowClassName == "SysTreeView32" and obj.role in (controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_CHECKBOX) and controlTypes.STATE_FOCUSED not in obj.states:
@@ -28,3 +169,14 @@ def event_NVDAObject_init(self, obj):
 	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
 		if obj.windowClassName == "SWT_Window0" and obj.role == controlTypes.ROLE_EDITABLETEXT:
 			clsList.insert(0, EclipseTextArea)
+
+		try:
+
+			# Autocompletion items are placed outside the main eclipse window
+			if (obj.role == controlTypes.ROLE_LISTITEM
+				and obj.parent.parent.parent.role == controlTypes.ROLE_DIALOG
+				and obj.parent.parent.parent.parent.parent == api.getDesktopObject()
+				and obj.parent.parent.parent.parent.simpleNext.role == controlTypes.ROLE_BUTTON):
+				clsList.insert(0, AutocompletionListItem)
+		except:
+			pass


Test patch: