Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » TreeViewer, how to jump say what element to show on top?
TreeViewer, how to jump say what element to show on top? [message #1123124] Wed, 02 October 2013 08:13 Go to next message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-Esteban
Messages: 30
Registered: February 2013
Member
I have spent hours and didn't find the solution for something which for me seems natural operation: How can I force the TreeViewer to show in the visiple part of the Tree a given element? In other words, how can I scroll it to the point where the first element to visualize is one specific?

_______________
A
 B
 C
_______________


And I want to visualize B as the first element:
_______________
 B
 C

_______________
(So the tree is scrolled down, programatically).


Notice I don't want to make B the root element, I just want to scroll up or down the whole model so that in the visible part (the View) shows the part of the Model which I want to be shown. In other words, I DONT'T want:

_______________
B

_______________
(B as root at the top-left).


I would really appreciate some help in here. Thanks a lot in advance Smile


ArkosX
Re: TreeViewer, how to jump say what element to show on top? [message #1123213 is a reply to message #1123124] Wed, 02 October 2013 10:15 Go to previous messageGo to next message
Thorsten Schlathölter is currently offline Thorsten Schlathölter
Messages: 208
Registered: February 2012
Location: Düsseldorf
Senior Member
Hi,
probably it is to easy to be the proper solution but try this:

treeViewer.getTree().setTopItem(toBeToRevealed);



Here is the modified Snippet002TreeViewer showing the functionality:

import java.util.ArrayList;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;

/**
 * A simple TreeViewer to demonstrate usage
 * 
 * @author Tom Schindl <tom.schindl@bestsolution.at>
 *
 */
public class Snippet002TreeViewer {
	private class MyContentProvider implements ITreeContentProvider {
		
		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
		 */
		public Object[] getElements(Object inputElement) {
			return ((MyModel)inputElement).child.toArray();
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
		 */
		public void dispose() {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
		 */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
		 */
		public Object[] getChildren(Object parentElement) {
			return getElements(parentElement);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
		 */
		public Object getParent(Object element) {
			if( element == null) {
				return null;
			}
			
			return ((MyModel)element).parent;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
		 */
		public boolean hasChildren(Object element) {
			return ((MyModel)element).child.size() > 0;
		}
		
	}
	
	public class MyModel {
		public MyModel parent;
		public ArrayList child = new ArrayList();
		public int counter;
		
		public MyModel(int counter, MyModel parent) {
			this.parent = parent;
			this.counter = counter;
		}
		
		public String toString() {
			String rv = "Item ";
			if( parent != null ) {
				rv = parent.toString() + ".";
			}
			
			rv += counter;
			
			return rv;
		}
	}
	
	public Snippet002TreeViewer(Shell shell) {
		shell.setLayout(new GridLayout());
		final TreeViewer v = new TreeViewer(shell);
		v.setLabelProvider(new LabelProvider());
		v.setContentProvider(new MyContentProvider());
		v.setInput(createModel());
		v.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
		Button button = new Button(shell, SWT.NONE);
		
		button.setText("Scroll");
		button.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				
				TreeItem[] items = v.getTree().getItems();
				TreeItem toBeToRevealed = null;
				for (TreeItem item: items)
				{
					MyModel modelData = (MyModel) item.getData();
					if (modelData.counter == 50)
					{
						toBeToRevealed = item;
					}
				}
				
				v.getTree().setTopItem(toBeToRevealed);
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}
		});
	}
	
	private MyModel createModel() {
		
		MyModel root = new MyModel(0,null);
		root.counter = 0;
		
		MyModel tmp;
		for( int i = 1; i < 100; i++ ) {
			tmp = new MyModel(i, root);
			root.child.add(tmp);
			for( int j = 1; j < i; j++ ) {
				tmp.child.add(new MyModel(j,tmp));
			}
		}
		
		return root;
	}
	
	public static void main(String[] args) {
		Display display = new Display ();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		new Snippet002TreeViewer(shell);
		shell.open ();
		
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		
		display.dispose ();
	}
}


HTH
Thorsten
Re: TreeViewer, how to jump say what element to show on top? [message #1123241 is a reply to message #1123213] Wed, 02 October 2013 10:54 Go to previous messageGo to next message
Thorsten Schlathölter is currently offline Thorsten Schlathölter
Messages: 208
Registered: February 2012
Location: Düsseldorf
Senior Member
Sry. I just realized that the example selects on top level. You were asking for second level. I was a little bit too fast.
Re: TreeViewer, how to jump say what element to show on top? [message #1123278 is a reply to message #1123241] Wed, 02 October 2013 11:50 Go to previous messageGo to next message
Thorsten Schlathölter is currently offline Thorsten Schlathölter
Messages: 208
Registered: February 2012
Location: Düsseldorf
Senior Member
Here you go now. It's basically the same as above.

Use:

treeViewer.reveal()

and

treeViewer.getTree().setTopItem()


Hope this time it helps.
Thorsten

Working example:

import java.util.ArrayList;

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;

/**
 * A simple TreeViewer to demonstrate usage
 * 
 * @author Tom Schindl <tom.schindl@bestsolution.at>
 *
 */
public class Snippet002TreeViewer {
	private static int sequence = 0;
	private class MyContentProvider implements ITreeContentProvider {
		
		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
		 */
		public Object[] getElements(Object inputElement) {
			return ((MyModel)inputElement).child.toArray();
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
		 */
		public void dispose() {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
		 */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
		 */
		public Object[] getChildren(Object parentElement) {
			return getElements(parentElement);
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
		 */
		public Object getParent(Object element) {
			if( element == null) {
				return null;
			}
			
			return ((MyModel)element).parent;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
		 */
		public boolean hasChildren(Object element) {
			return ((MyModel)element).child.size() > 0;
		}
		
	}
	
	public class MyModel {
		public MyModel parent;
		public ArrayList child = new ArrayList();
		public int counter;
		public int id;
		
		public MyModel(int id) {
			this.id = id;
		}
		
		public MyModel(int counter, MyModel parent) {
			this.parent = parent;
			this.counter = counter;
			this.id = sequence++;
		}
		
		public String toString() {
			String rv = "Item ";
			if( parent != null ) {
				rv = parent.toString() + ".";
			}
			
			rv += counter;
			
			rv += "("+id+")";
			
			return rv;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + id;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			MyModel other = (MyModel) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (id != other.id)
				return false;
			return true;
		}

		private Snippet002TreeViewer getOuterType() {
			return Snippet002TreeViewer.this;
		}

	
		
		
	}
	
	public Snippet002TreeViewer(Shell shell) {
		shell.setLayout(new GridLayout());
		final TreeViewer v = new TreeViewer(shell);
		v.setLabelProvider(new LabelProvider());
		v.setContentProvider(new MyContentProvider());
		v.setInput(createModel());
		v.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
		Button button = new Button(shell, SWT.NONE);
		
		button.setText("Scroll");
		button.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				// I don't know how you want to define the Item to top. I assume you go via a TreePath.
				
				// Path to the element to set to top
				final TreePath path = new TreePath(new MyModel[]{new MyModel(1036), new MyModel(1059)});
				
				// First make sure the item to be set to top is visible
				v.reveal(path);

				// Find the item to top
				TreeItem toBeToRevealed = getItemToTop(path);

				if (toBeToRevealed!=null)
				{
					v.getTree().setTopItem(toBeToRevealed);
					TreeItem topItem = v.getTree().getTopItem();
					if (topItem!=toBeToRevealed)
					{
						System.err.println("failed to reveal element at top!");
					}
				}
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}
			
			private TreeItem getItemToTop(TreePath path) {
				// You might subclass TreeViewer to be able to access findItem(path).
				// Here: use recursive approach via TreeItems.
				TreeItem[] items = v.getTree().getItems();
				return findItem(path, items, 0);
				
			}

			private TreeItem findItem(TreePath path, TreeItem[] items, int lvl) {
				
				if (items==null)
				{
					return null;
				}
				
				Object segment = path.getSegment(lvl);
				for (TreeItem item: items)
				{
					MyModel itemData = (MyModel) item.getData();
					if (itemData!=null && itemData.equals(segment))
					{
						if (lvl==path.getSegmentCount()-1)
						{
							return item;
						}
						else
						{
							TreeItem toBeRevealed = findItem(path, item.getItems(), ++lvl);
							return toBeRevealed;
						}
					}
				}
				
				return null;
			}
		}
		);
	}
	
		
	
	private MyModel createModel() {
		
		MyModel root = new MyModel(0,null);
		root.counter = 0;
		
		MyModel tmp;
		for( int i = 1; i < 100; i++ ) {
			tmp = new MyModel(i, root);
			root.child.add(tmp);
			for( int j = 1; j < i; j++ ) {
				tmp.child.add(new MyModel(j,tmp));
			}
		}
		
		return root;
	}
	
	public static void main(String[] args) {
		Display display = new Display ();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		new Snippet002TreeViewer(shell);
		shell.open ();
		
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		
		display.dispose ();
	}
}
 



[Updated on: Wed, 02 October 2013 11:51]

Report message to a moderator

Re: TreeViewer, how to jump say what element to show on top? [message #1123473 is a reply to message #1123278] Wed, 02 October 2013 15:51 Go to previous messageGo to next message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-Esteban
Messages: 30
Registered: February 2013
Member
Thanks, but setInput, doesn't change the root? What I want is not to set the root to B, which result in the example would be:

__________
B


____
(B on the top-left and its children hanging -in this example none-).


But to show the B element on top (not top-left), so the equivalent to scrolling it up or down until the element is in the first visible row. In other words, I don't want to change the model, I want to apply the view to show other part of the model.

_________
B
C

_________

Thanks again,
Luis


ArkosX

[Updated on: Wed, 02 October 2013 15:52]

Report message to a moderator

Re: TreeViewer, how to jump say what element to show on top? [message #1124121 is a reply to message #1123473] Thu, 03 October 2013 07:54 Go to previous messageGo to next message
Thorsten Schlathölter is currently offline Thorsten Schlathölter
Messages: 208
Registered: February 2012
Location: Düsseldorf
Senior Member
Hi,
sorry but I don't get it. The code above scrolls the tree to a given row, so that the given row is exactly at the top of the view. It does not change the viewer input. As far as I understand it's what you have been asking for.

Of course it only works if the viewer can be scrolled at all. Is that your point? If the content is large enough to fit in the visible area of the control, then you cannot scroll. In that case you would indeed have to change the input or the contentprovider. Can you elaborate on the use case of your scenario? What is so bad in changing the model?

Regards
Thorsten

[Updated on: Thu, 03 October 2013 07:55]

Report message to a moderator

Re: TreeViewer, how to jump say what element to show on top? [message #1128231 is a reply to message #1124121] Mon, 07 October 2013 13:31 Go to previous messageGo to next message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-Esteban
Messages: 30
Registered: February 2013
Member
Hi Thorsten,
I am Sorry.
I think I answered too fast.
I had been checking setTopoItem before and the result -it seemed- was that it was resetting putting the root node, not "scrolling".
I should try your proposal in detail. I see that the "tree".
(BTW, no I don't use the Path but always the Item).
I'll let you know how it works out.
Thanks,
LF


ArkosX
Re: TreeViewer, how to jump say what element to show on top? [message #1129309 is a reply to message #1123124] Tue, 08 October 2013 14:00 Go to previous message
Luis Fernando Robledano-Esteban is currently offline Luis Fernando Robledano-Esteban
Messages: 30
Registered: February 2013
Member
Hi again!
It's working! I have some other issue but the root cause is another thing.

I think in the end it was only about the setTopItem, and the key was the findItem. I think in my previously trials I was basically assuming that I could move from one item to another by index and that lead to Out-of index exceptions (which I thought was for the root element).

BTW, I had already my TreeViewer as a class extending TreeViewer, therefore I could use the native "findItem(object)" Very Happy . In any case I appreciate that you also suggested me to extend that, because although I was doing it, I was a little bit scared. TreeViewer documentation states that "TreeViewer is not intended to be subclassed" but I have no idea why. It made a lot of sense for me (and I tend to encapsulate things a lot and inheritance is many times a great approach), and it does work.

Thanks for your help! Smile


ArkosX
Previous Topic:How to wrap the description on the first page of wizard
Next Topic:Observing map doesn't update the UI
Goto Forum:
  


Current Time: Thu Oct 23 04:38:07 GMT 2014

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

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