Home > SWT - JFace > CheckboxTreeViewer

CheckboxTreeViewer

March 3rd, 2009

Screenshot of application with CheckboxTreeViewer

Screenshot of application with CheckboxTreeViewer

Today I found out that quite a lot of people struggle with the CheckboxTreeViewer class and especially with the methods:

  • setChecked(Object element, boolean state)
  • setCheckedElements(Object[] elements)

Those names are very selfexplaining, but still, getting those methods to work took me some time. To shorten up your building time, I will explain how to use the setCheckedElements method in this post. But first I’ll start with the beginning, and that’s the creation of a CheckboxTreeViewer…

So let’s assume you have a Treestructure that you would like to visualize and that structure is build up by two different parts, lets call them Folders and Files. Now, to create the Treestructure we think about a file system, where every Folder can contain zero or multiple Files. You can see a screenshot of the final application on the right, I hope that my structure is a little bit more understandable once you’ve seen the application.

So what do we need to get a CheckboxTreeViewer in our application? Well, you need an CheckboxTreeViewer object and at least one ContentProvider and a LabelProvider.

So lets first start with the ContentProvider

import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;

import be.jcreation.checkboxtreeviewerexample.model.FolderHandler;
import be.jcreation.checkboxtreeviewerexample.model.interfaces.File;
import be.jcreation.checkboxtreeviewerexample.model.interfaces.Folder;

public class TreeContentProvider implements ITreeContentProvider {

	@Override
	public Object[] getChildren(Object parentElement) {
		if(parentElement instanceof Folder){
			return ((Folder) parentElement).getAllFiles().toArray();
		}
		return null;
	}

	@Override
	public Object getParent(Object element) {
		if(element instanceof File){
			return ((File) element).getFolder();
		}
		return null;
	}

	@Override
	public boolean hasChildren(Object element) {
		if(element instanceof Folder)
			return true;
		return false;
	}

	@Override
	public Object[] getElements(Object inputElement) {
		if(inputElement instanceof Folder){
			return ((Folder) inputElement).getAllFiles().toArray();
		}
		return FolderHandler.getInstance().getAllFolders().toArray();
	}

	@Override
	public void dispose() {}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput,
            Object newInput) {}

}

The major part of the above code can be found in any book about JFace, but it’s the method getElements(Object inputElement) that has been causing me a lot of problems. As you can see, you also have to keep in mind that the Treestructure should be used here also. So if the inputElement is an object of the class Folder, you should return the children of that object. I assume, I should check the code to be sure of course, that this method is used to search through the structure…

The used LabelProvider isn’t that spectacular, but to give you all the code, here we go:

import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.graphics.Image;

import be.jcreation.checkboxtreeviewerexample.model.interfaces.File;
import be.jcreation.checkboxtreeviewerexample.model.interfaces.Folder;

public class LabelProvider implements ILabelProvider {

    @Override
    public Image getImage(Object element) {
        return null;
    }

    @Override
    public String getText(Object element) {
        if(element instanceof Folder)
            return ((Folder) element).getName();
        else if(element instanceof File)
            return ((File) element).getName();
        return null;
    }

    @Override
    public void addListener(ILabelProviderListener listener) {}

    @Override
    public void dispose() {    }

    @Override
    public boolean isLabelProperty(Object element, String property) {
        return false;
    }

    @Override
    public void removeListener(ILabelProviderListener listener) {}

}

And last, but not least, how to create the CheckboxTreeViewer, and how to use that setCheckedElements method!

        tv = new CheckboxTreeViewer(panel, SWT.NONE);
        tv.setContentProvider(new TreeContentProvider());
        tv.setLabelProvider(new LabelProvider());
        tv.setInput("root");
        // When the parent is checked, all children should be checked to
        tv.addCheckStateListener(new ICheckStateListener(){
            public void checkStateChanged(CheckStateChangedEvent event){
                if(event.getChecked()){
                    tv.setSubtreeChecked(event.getElement(), true);
                }
            }
        });        

        Button loadSomeSelection = new Button(parent, SWT.PUSH);
        loadSomeSelection.setText("Load");
        loadSomeSelection.addSelectionListener(new SelectionAdapter(){
            @Override
            public void widgetSelected(SelectionEvent e) {
                tv.setCheckedElements(FolderHandler.getInstance().
                                getSomeFilesToSelect().toArray());
            }
        });

If you have read the code carefully, you are now probably wondering what the method getSomeFilesToSelect is returning? Well:

    public List<File> getSomeFilesToSelect(){
        List<File> selectedFiles = new ArrayList<File>();
        for(Folder f : allFolders){
            if(f.getAllFiles().size() > 2){
                selectedFiles.add(f.getAllFiles().get(2));
            }else if(f.getAllFiles().size()>1){
                selectedFiles.add(f.getAllFiles().get(1));
            }else if(f.getAllFiles().size()>0){
                selectedFiles.add(f.getAllFiles().get(0));
            }
        }
        return selectedFiles;
    }

This is just some random selection, well not really random but every time the last child of a parent. But to make my point clear, as you can see, I’m giving a list of Files to the setCheckedElements method and those Files are checked (as the screenshot at the top of the page is showing you).

I hope this post is helping those who had the same problem with the CheckboxTreeViewer as I had. And to end my post, I’ll give you the link to my Ecipse Project. It’s an RCP-application to keep it simple.

Jan

Jan SWT - JFace , ,

  1. réno
    November 2nd, 2009 at 22:27 | #1

    Hello jan

    Your post surely help find my way in understanding a little bit more what checkboxtreeviewer it’s all about. i’m planning to learn Eclipse RCP this is my first day so it will be very helpfull if you could make your entire eclipse rcp project available. great post thank jan .

    and keep up the good work

  2. November 3rd, 2009 at 17:03 | #2

    Hi Réno,

    The entire Eclipse RCP Project was already available (at the end of the post), but there was something wrong with the URL! I have fixed it now!!

    I hope this can help you!

    Goodluck! If you should have any other questions about Eclipse RCP, don’t hesitate to ask them…

    Jan

  3. réno
    November 11th, 2009 at 22:51 | #3

    Hello Jan

    yes now i can the download link is working thank you. because of some other stuff to do i didn’t have much time to go further with Eclipse rcp, tomorow i’ll be on it the all day ( i hope not but yeah most of it). So just to give you an idea of what i wanna do. i’m learning rcp by doing a small “pet” project that will have two domain model class : server & alarm (associated with each server). i wanna build a treecheckbox with the following hiérarchy in mind: folder–>server–>alarm. A folder can contain multiple other folder. server have multiple monitoring alarm. So folder it’s just a convient way of keeping things in order. Folder will serve as a container for “test” or “preprod” or “prod” it can also be useful as container for defining the type of server component on the plateforme : “webfront” “appserver” “BDD”. i post is getting to long “lol” sorry i’m kind of exciting because new to java world and eclipse. but to resume here an example:

    Preprod (environnement folder)
    -> WEB (folder)
    -> web01 (reverseproxy)
    -> Fo-Instance (alarm)
    -> Bo-Instance (alarm)
    -> sslcheck (alarm)
    etc …
    -> web02
    -> BDD (database folder)
    -> Ora01
    liste of alarm
    TEST ( environnement folder)
    and so on

    So i was inspired by your work here, but as i say i’m totaly discovering things here so it may take some time before i come up with a proper solution.
    Sorry about the looonng i’m post.

    have a nice day

    thank for your help Jan.

    Réno

  1. No trackbacks yet.