Question

I am developing a RCP application with a TreeViewer. While there are good number of articles to explain how to add editing support to the Viewer (and how changes in view are updated in the model), I don't find much for updating the Treeview when the underlaying model changes. my question in short:

TreeView ----> Model updation ------ there are lots of examples

Model ----> Treeview updation ----- this is my question

Edit: This is what I tried and it works. comments please

viewer.getTree().addKeyListener(new KeyListener(){

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

        if(e.keyCode==SWT.F3){
            System.out.println("F3 pressed... new element will be added");
            TreeParent root = (TreeParent) viewer.getInput();
            TreeParent activityRoot = (TreeParent) root.getChildren()[0];
            activityRoot.addChild(new TreeObject("NEW_ACTIVITY"));
            //viewer.update(root, null);
            viewer.refresh();
        }

    }

    });
Was it helpful?

Solution

The data model is provided by your content provider, TreeViewer does not provide any means of changing this data - you must do that it your own code. When you have changed to model you can use the following methods to tell the TreeViewer about the change:

If you have just changed what needs to be shown for a single item in the tree use

TreeViewer.update(object, null);

to get that item in the tree updated. There is also an array version of this to update multiple objects.

If you have added or removed objects in the tree use

TreeViewer.refresh();

to rebuild the whole tree or

TreeViewer.refresh(object);

to refresh the part of the tree start at object.

To tell the tree about adding and removing objects there are

TreeViewer.add(parent, object);
TreeViewer.remove(object);

there are also array variants of these.

To help the TreeViewer find the objects call

TreeViewer.setUseHashlookup(true);

(must be called before TreeViewer.setInput). Since this uses a hash table the objects should have sensible hashCode and equals methods. You can also use TreeViewer.setComparer to specify a different class to do the hash code and comparison.

OTHER TIPS

Based on the comments in this thread,one of the eclipse corner articles on using TreeViewer and few experimenting I had created a working model.

Here are the steps:

Create a listener interface like the following

public interface TreeModelListener extends EventListener {
    public void onDelete(TreeObject obj);
}

Let the tree Content provider to add listeners to each tree model item and implement this interface like below

public class TreeContentProvider implements  IStructuredContentProvider,ITreeContentProvider,TreeModelListener {

TreeViewer tv;
public TreeContentProvider(TreeViewer tv){
    this.tv=tv;
}

int cnt=0;
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
    cnt ++;
    System.out.println("inputChanged() called "+oldInput+" new: "+newInput);
    if(newInput!=null){

        ((TreeParent)newInput).setListener(this);
        TreeObject []items = ((TreeParent)newInput).getChildren(); 
        for(TreeObject obj : items){
            if(obj instanceof TreeParent){
                ((TreeParent) obj).setListener(this);
            }
        }

    }
}

....

@Override
public void onDelete(TreeObject obj) {
    System.out.println("Delete of "+obj+" handled by content handler ");
    TreeParent parent = obj.getParent();
    if(parent.getChildren().length<=1){
        return;
    }
    parent.removeChild(obj);
    this.tv.refresh();
}

}

Add a method to the TreeModel class as below . And obviously TreeParent class should have an ArrayList of listeners that is being used in #1 above

public void fireChildDelete(final TreeObject obj){

    if(this.listener!=null){
        new Runnable(){

            @Override
            public void run() {
                System.out.println("New thread spawned with ID "+Thread.currentThread().getId());
                listener.onDelete(obj);
            }

        }.run();
    }
}

Finally add KeyListener to the TreeViewer Object to handle Delete key as below:

tv.getTree().addKeyListener(new KeyListener(){

        @Override
        public void keyPressed(KeyEvent e) {

        }

        @Override
        public void keyReleased(KeyEvent e) {

            if(e.keyCode==SWT.F3){
                System.out.println("F3 pressed... new element will be added");
                TreeParent root = (TreeParent) tv.getInput();
                TreeParent activityRoot = (TreeParent) root.getChildren()[0];
                activityRoot.addChild(new TreeObject("NEW_ACTIVITY"));
                //viewer.update(root, null);
                tv.refresh();
            }

            if(e.keyCode==SWT.DEL){


                System.out.println("DEL key pressed... element will be deleted "+((Tree)e.getSource()).getSelection().length);

                if(((Tree)e.getSource()).getSelection().length>0){
                    final IStructuredSelection selection = (IStructuredSelection) tv
                              .getSelection();
                    System.out.println("DEL#2 key pressed... element will be deleted "+selection.getFirstElement().getClass());

                    TreeParent parent =  ((TreeObject)selection.getFirstElement()).getParent();
                    parent.fireChildDelete((TreeObject) selection.getFirstElement());
                    //tv.remove(selection.getFirstElement());
                    //viewer.update(viewer.getInput(),null);
                    //tv.refresh();
                }
            }


        }

    });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top