With your initial design, you can't do it. Why are dogs and cats on the same level in the tree? Levels usually contain same objects (because why would you put your cousins under your parents?).
OK, cats and dogs are both Animals, but then make them extending Animal
class and use something like this:
class Person {
List<Animal> pets; // both dog and cats
}
IObservableFactory observableFactory = new IObservableFactory() {
public IObservable createObservable(final Object target) {
return BeanProperties.list("pets").observe(target);
}
};
And even this would not be a good idea, in case you want to display properties which are only related to cats, dogs, rabbits... .
I am not sure, why you want to use observable content provider (as usually Tree is convenient way to just display something). Wouldn't it be enough for you to use ITreeContentProvider
? In this case you could stick with you model of having separate dogs and cats collections and do something like this:
class PetsContentProvider immplements ITreeContentProvider {
public boolean hasChildren(Object element) {
if (element instanceof Person) {
Person person = (Person) element;
return person.getCats().size > 0 || person.getDogs().size() > 0;
}
return false;
}
public Object getParent(Object element) {
// TODO: still better to have a common class
if((element instanceof Dog) || (element instanceof Cat)) {
// cast to dog or cat (or better animal)
// Animal pet = (Animal) element;
return pet.getOwner();
}
return null;
}
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof Person) {
Person person = (Person) parentElement;
return person.getCats().toArray(); // and dogs
}
return EMPTY_ARRAY;
}
}
For more information, please see this very good article on JFace Trees.
And just traditionally Vogella's article on JFaceData Binding.