Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » JFace Treviewer: How to handle a "Post"-Collapse/-Expand in TreeViewer
JFace Treviewer: How to handle a "Post"-Collapse/-Expand in TreeViewer [message #1129317] Tue, 08 October 2013 14:07 Go to next message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-EstebanFriend
Messages: 32
Registered: February 2013
Member
Hi people,
I need to do some operations in a TreeViewer after an element has collapsed/expanded.

"ITreeViewerListener.treeCollapse(..).."
seems to receive the call before the default behavior has been executed but I need to do something after that.
How can I do that?

I see I can do something with
treviewer.getTree().getListeners()...
and maybe I can change orders, but this seems a little bit too complicated (how do I know which one is my listener and which one is the default one, for example). Is this the right approach?

Thanks a lot,


ArkosX
Re: JFace Treviewer: How to handle a "Post"-Collapse/-Expand in TreeViewer [message #1143628 is a reply to message #1129317] Fri, 18 October 2013 10:06 Go to previous message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-EstebanFriend
Messages: 32
Registered: February 2013
Member
Finally I found a solution.
The idea is to program a job that is queued and will be executed after Eclipse has finished doing it's stuff collapsing the tree and scrolling everything up.

private final class MyViewerTreeListener implements ITreeViewerListener
{
	public void treeCollapsed(TreeExpansionEvent treeexpansionevent)
	{

		// Do something with before collapsing,
		// probably using the info on the Element.
		// For example:
		Object objectCollapsed = treeexpansionevent.getElement();
		System.out.println(object.toString());

		Display.getCurrent().asyncExec(new Runnable() {
			@Override
			public void run() {
				// Do something with AFTER collapsing,
				// probably using the info on the Element.
				// Remember that to access local variable
				// you have to deine it final in the host
				// class/function. In this example it would apply
				// to treeexpansionevent or objectCollapsed
				...
			}//- run()
		}//- Runnable -anonymous class-
	}//- treeCollapsed() --
}//- MyTreeViewerTreeListener 


Now, IMO this has some flaws, but I didn't find any other natural way of doing it neither I got any answer here or in other forums, so I assume this is the only way:
1) Design/Architectural, why handling the even before collapsing is different than after collapse? why to deal with threads (I know the answer is the dependency on Eclipse/GUI mono-threading but this should be encapsulated from its use).
2) Design/Architectural, anonymous stuff is evil: i) if I cannot represent it in a diagram (UML) it is difficult more difficult to handle in my mind, ii) mixes static and dynamic (behavioral).
3) Learning-curve. It took me days to find the solution. I don't even really understand all what is happening.
4) Learning curve. It is necessary to know: i) about threads, probably sync and async stuff, Runnable... ii) Display stuff, iii) the commented anonymous classes use of local variables (or define public members)
IMO, An event that should be the direct implementation of a method which is called after collapse requires the programmer to know too much, and I use it once, and then I will have to look for it again if I use it again in several months from now.
5) Is it sure that the method is going to be executed? couldn't it be that for some magical reason this programmed task is finally executed before the other tasks Eclipse has? and I remind that there is a lot of magic in Eclipse (things happening under the table). In any case this is generating dependencies.

Am I the only one concerned about design, encapsulation, learning curve...?

I understand that ther are some or many good Eclipse programmers that know all of this by heart, but is that the way to get other people into Eclipse? And I mean beyond the use of Eclipse for basic Java console applications in class.

My proposal to get things nicely encapsulated for this case in a different comment.

package org.eclipse.jface.viewers;


/*** BaseTreeViewerTreeListener 
* This class will be extended, and 2 methods overridden :
* -void beforeTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent );
* -void afterTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent );
*
*/
public class BaseTreeViewerListener implements ITreeViewerListener
{
	public /* if possible private */
         void treeCollapsed( final TreeExpansionEvent treeexpansionevent )
	{
		beforeTreeCollapsedEventHandler( treeexpansionevent );

		Display.getCurrent().asyncExec(new Runnable() {
			@Override
			public void run() {
				afterTreeCollapsedEventHandler( treeexpansionevent );
			}//- run()
		}//- Runnable -anonymous class-
	}//- treeCollapsed() --
}//- BaseTreeViewerTreeListener 



This class would be part of JFace.
Now a "user" of JFace would only need to do:

package mypackage;

import org.eclipse.jface.viewers.BaseTreeViewerTreeListener;
import org.eclipse.jface.viewers.TreeExpansionEvent; // btw, to call expansion event when it handles collapseing event too... :O


/*** MyTreeViewerTreeListener 
* Overrides the 2 methods:
* -void beforeTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent );
* -void afterTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent );
*
*/
public class MyTreeViewerListener extends BaseTreeViewerListener
{
	/***
	*
	*/
	void beforeTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent )
	{
		// Do something before collapsing,
		// probably using the info on the Element.
		// For example:
		Object objectCollapsed = treeexpansionevent.getElement();
		System.out.println(object.toString());

	}//- beforeTreeCollapsedEventHandler() - 

	/***
	*
	*/
	void afterTreeCollapsedEventHandler( TreeExpansionEvent treeexpansionevent );
	{
		// Do something with before collapsing,
		// probably using the info on the Element.
		// For example:
		// I check what is the new element on top, because Eclipse TreeViewer
		// may have changed it scrolling up in order not to have empty
		// rows at the bottom.
		// 

		System.out.println(object.toString());
	}//- afterTreeCollapsedEventHandler()

}//- MyTreeViewerTreeListener 



Doesn't it make sense?
In this case the implementation is encapsulated. A user only need to care about knowing BaseTreeViewerTreeListener and TreeExpansionEvent (no threads, no Displays, no...). (Note: I would actually encapsulate much more all the TreeListeners stuff of JFace, which requires to be awaree of much of SWT...).


In any case for the people looking for the answer to my orioginal question, the first code will help. For the people able to reach eclipse (committers) they may agree with the generalized proposal.

Thanks to all and criticism is welcome! Smile


ArkosX
Previous Topic:Observing map doesn't update the UI
Next Topic:CheckboxTreeViewer don't show expand node icon
Goto Forum:
  


Current Time: Tue Dec 23 05:16:49 GMT 2014

Powered by FUDForum. Page generated in 0.01582 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software