Monday 23 January 2017

swt : CheckBoxTreeViewer Tutorial

CheckBoxTreeViewer is used to represent items in the form of tree, and provides checkboxe on each node. CheckboxTreeViewer provides following constructors to instantiate.

Constructor
Description
CheckboxTreeViewer(Composite parent)
Creates a tree viewer on a newly-created tree control under the given parent.
CheckboxTreeViewer(Composite parent, int style)
Creates a tree viewer on a newly-created tree control under the given parent.
CheckboxTreeViewer(Tree tree)
Creates a tree viewer on the given tree control.

In this post, I am going to explain how to define checkbox tree viewer by extending the 'CheckboxTreeViewer' class. Since ‘MyCheckBoxTreeViewer’ extends the class CheckboxTreeViewer, you need to use one of the constructors of CheckboxTreeViewer.

We add some more requirements to ‘MyCheckBoxTreeViewer’.

1.   Get notified on any change in checked state of items
2.   Control check, uncheck and gray check of the checkbox.

Let’s see the first requirement.

Get notified on any change in checked state of items
By implementing the interface 'ICheckStateListener', you will be notified of changes to the checked state of items in checkbox viewers. This interface provide 'checkStateChanged' method, it is called when there is a change to the checked state of an element.

Method
Description
void checkStateChanged(CheckStateChangedEvent event)
Notifies of a change to the checked state of an element.

Control check, uncheck and gray check of the checkbox.
By implementing ICheckStateProvider interface, we can provide checked and grayed state information about data in trees or tables.

ICheckStateProvider interface provides following methods to control checked, unchecked and grayed behavior of tree items.

Method
Description
boolean isChecked(Object element)
Indicates if an element's representation should appear as checked or gray instead of unchecked. If this method returns true the isGrayed(Object) method will determine whether the check box displays a check mark ("checked") or a box ("grayed").
boolean isGrayed(Object element)
Indicates whether the check box associated with an element, when checked as indicated by the isChecked(Object) method, should display the gray (boxed) state instead of the check mark.

Please read the following points carefully.

If isChecked is false and isGrayed is false/true then checkbox is unchecked only.

If isChecked is true and isGrayed is false then checkbox is completely checked.

If isChecked is true and isGrayed is true then checkbox is gray checked.

To satisfy requirements 1 & 2 we need to tell MyCheckBoxTreeViewer class about checkStateProvider and ICheckStateListener implementations.

public void setCheckStateProvider(ICheckStateProvider checkStateProvider)
Sets the ICheckStateProvider for this CheckboxTreeViewer. The check state provider will supply the logic for deciding whether the check box associated with each item should be checked, grayed or unchecked.

public void addCheckStateListener(ICheckStateListener listener)
Adds a listener for changes to the checked state of elements in this viewer. Has no effect if an identical listener is already registered.

By setting above two methods to appropriate implementations, we can satisfy the requirements. Following is the sample structure of MyCheckBoxTreeViewer class.
public class MyCheckBoxTreeViewer extends CheckboxTreeViewer implements ICheckStateListener, ICheckStateProvider {

 public MyCheckBoxTreeViewer(Composite parent, int style) {
  super(parent, style);
  ColumnViewerToolTipSupport.enableFor(this);
  initializeTree();
 }

 private void initializeTree() {
  setCheckStateProvider(this);
  addCheckStateListener(this);
 }

 @Override
 public boolean isChecked(Object arg0) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public boolean isGrayed(Object arg0) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public void checkStateChanged(CheckStateChangedEvent arg0) {
  // TODO Auto-generated method stub

 }

}


Now let’s see how to provide the content to MyCheckBoxTreeViewer.

CheckBoxTreeViewer class provides 'setContentProvider' method to set the content provider.

public void setContentProvider(IContentProvider provider)

So to set the content provider to myCheckBoxTreeViewer class, we need to implement IContentProvider.

By implementing 'ITreeContentProvider' interface, you are going to provide implementation for dispose, inputChanged, getChildren,
getElements, getParent, hasChildren method.

For our implementation purpose, I am going to implement getChildren, hasChildren, getElements methods.


Following is the dummy implementation of MyCheckBoxTreeContentProvider class.
public class MyCheckBoxTreeContentProvider implements ITreeContentProvider{

 @Override
 public void dispose() {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public Object[] getChildren(Object arg0) {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public Object[] getElements(Object arg0) {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public Object getParent(Object arg0) {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public boolean hasChildren(Object arg0) {
  // TODO Auto-generated method stub
  return false;
 }

}

Let’s try to provide implementation for checkStateChanged method
public void checkStateChanged(CheckStateChangedEvent event)
As I said previously, this method notifies of a change to the checked state of an element. By using CheckStateChangedEvent instance, we can get the element whose check state changed. By using the inbuilt 'findItem' method, we can get the widget which represents the given element. It returns the corresponding widget, or null if none.

Now let’s see how to provide labels to the tree viewer. Since we provide content to the tree viewer by implementing ‘ITreeContentProvider’, we need to provide a label for every tree item. We can do this by using ‘setLabelProvider’ method.

Following is the signature of the ‘setLabelProvider’ method.

public void setLabelProvider(IBaseLabelProvider labelProvider)


CellLabelProvider implements IBaseLabelProvider  interface. So by extending CellLabelProvider class, you can provide custom label provider for 'MyCheckBoxTreeViewer'.
public class MyCheckBoxLabelProvider extends CellLabelProvider {

 @Override
 public void update(ViewerCell arg0) {
  
 }

}

Orders the elements
By calling the setSorter method on check box tree viewer, you can order the elements. Following is the signature of the setSorter method.

public void setSorter(ViewerSorter sorter)

public class MyCheckBoxTreeSorter extends ViewerSorter {
 @Override
 public int compare(Viewer viewer, Object left, Object right) {
  return 0;
 }
}

Following are the finalized classes.

MyCheckBoxTreeViewer : extends CheckboxTreeViewer class

MyCheckBoxTreeContentProvider : Implements ITreeContentProvider interface, and provide content to MyCheckBoxTreeViewer

MyCheckBoxLabelProvider : Provide labels to the content of MyCheckBoxTreeViewer

MyCheckBoxTreeSorter : Order the elements of MyCheckBoxTreeViewer

It is time to develop an application using these. Following is the requirement.

Build an application, where all the managers are the childs of your organization tree. Each manager has 1 (or) more reportees under him.

a.   Manager node should be checked, if all the reportees come to the office today.
b.   Manager node should be gray checked, if some reportees (not all) come to office today
c.    Manager node should be unchecked, if no reportee come today.
d.   You can check (or) uncheck the Manager node.
e.   If Manager node is checked, then all the employee nodes also should be checked.
f.    If Manager node is unchecked, then all the employee nodes should be unchecked.

Let’s design above application. Following is the complete working example.


Employee.java
package com.sample;

public class Employee {
 private String name;
 private boolean inOffice;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public boolean isInOffice() {
  return inOffice;
 }

 public void setInOffice(boolean inOffice) {
  this.inOffice = inOffice;
 }

}

Manager.java
package com.sample;

import java.util.ArrayList;
import java.util.List;

public class Manager {
 private String name;
 private final List<Employee> employees = new ArrayList<> ();

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public List<Employee> getEmployees() {
  return employees;
 }

}


Organization.java
package com.sample;

import java.util.ArrayList;
import java.util.List;

public class Organization {
 private String name;
 private List<Manager> managers = new ArrayList<>();

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public List<Manager> getManagers() {
  return managers;
 }

}

DataUtil.java
package com.sample;

public class DataUtil {

 public static Organization getOrganization() {
  Organization oranization = new Organization();
  oranization.setName("XYZ Corporation");

  Manager manager1 = new Manager();
  manager1.setName("Mukund Dixit");

  Manager manager2 = new Manager();
  manager2.setName("Anand Bandaru");

  Manager manager3 = new Manager();
  manager3.setName("Shreyas Desai");

  Manager manager4 = new Manager();
  manager4.setName("VadiRaj");

  Employee emp1 = new Employee();
  emp1.setInOffice(true);
  emp1.setName("Keerthi Shetty");

  Employee emp2 = new Employee();
  emp2.setInOffice(true);
  emp2.setName("Karthik");

  Employee emp3 = new Employee();
  emp3.setInOffice(true);
  emp3.setName("Brijesh");

  Employee emp4 = new Employee();
  emp4.setInOffice(true);
  emp4.setName("Deepank Bansal");

  Employee emp5 = new Employee();
  emp5.setInOffice(true);
  emp5.setName("Reshmi George");

  Employee emp6 = new Employee();
  emp6.setInOffice(true);
  emp6.setName("Janaki Sriram");

  Employee emp7 = new Employee();
  emp7.setInOffice(false);
  emp7.setName("Aravind Phaneendra");

  Employee emp8 = new Employee();
  emp8.setInOffice(true);
  emp8.setName("Nagendra");
  
  Employee emp9 = new Employee();
  emp9.setInOffice(true);
  emp9.setName("Maruthi");
  
  Employee emp10 = new Employee();
  emp10.setInOffice(true);
  emp10.setName("Piyush");
  
  Employee emp11 = new Employee();
  emp11.setInOffice(true);
  emp11.setName("Shanmugham");
  
  Employee emp12 = new Employee();
  emp12.setInOffice(false);
  emp12.setName("Phalgun Garimella");
  
  Employee emp13 = new Employee();
  emp13.setInOffice(false);
  emp13.setName("Sankalp");
  
  Employee emp14 = new Employee();
  emp14.setInOffice(false);
  emp14.setName("Arpan");
  
  Employee emp15 = new Employee();
  emp15.setInOffice(false);
  emp15.setName("Sandesh");
  
  Employee emp16 = new Employee();
  emp16.setInOffice(false);
  emp16.setName("Senthil");

  manager1.getEmployees().add(emp1);
  manager1.getEmployees().add(emp2);
  manager1.getEmployees().add(emp3);
  manager1.getEmployees().add(emp4);
  
  manager2.getEmployees().add(emp5);
  manager2.getEmployees().add(emp6);
  manager2.getEmployees().add(emp7);
  manager2.getEmployees().add(emp8);

  manager3.getEmployees().add(emp9);
  manager3.getEmployees().add(emp10);
  manager3.getEmployees().add(emp11);
  
  manager4.getEmployees().add(emp12);
  manager4.getEmployees().add(emp13);
  manager4.getEmployees().add(emp14);
  manager4.getEmployees().add(emp15);
  manager4.getEmployees().add(emp16);
  
  oranization.getManagers().add(manager1);
  oranization.getManagers().add(manager2);
  oranization.getManagers().add(manager3);
  oranization.getManagers().add(manager4);
  
  return oranization;
 }
}

MyCheckBoxLabelProvider.java
package com.sample;

import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ViewerCell;

public class MyCheckBoxLabelProvider extends CellLabelProvider {

 @Override
 public void update(ViewerCell cell) {
  Object element = cell.getElement();

  if (element instanceof Organization) {
   cell.setText("Org: " + ((Organization) element).getName());
  } else if (element instanceof Manager) {
   cell.setText("M: " + ((Manager) element).getName());
  } else {
   cell.setText("Emp: " + ((Employee) element).getName());
  }
 }

}

MyCheckBoxTreeContentProvider.java
package com.sample;

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

public class MyCheckBoxTreeContentProvider implements ITreeContentProvider {

 public MyCheckBoxTreeContentProvider() {
 }

 @Override
 public void dispose() {
  // TODO Auto-generated method stub

 }

 @Override
 public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
  // TODO Auto-generated method stub

 }

 @Override
 public Object[] getChildren(Object obj) {

  if (obj instanceof Organization) {
   return ((Organization) obj).getManagers().toArray();
  }

  if (obj instanceof Manager) {
   return ((Manager) obj).getEmployees().toArray();
  }

  return new Object[0];
 }

 @Override
 public Object[] getElements(Object arg0) {
  Object[] roots = new Object[1];
  roots[0] = DataUtil.getOrganization();
  return roots;
 }

 @Override
 public Object getParent(Object arg0) {
  // TODO Auto-generated method stub
  return null;
 }

 @Override
 public boolean hasChildren(Object obj) {
  if (obj instanceof Organization || obj instanceof Manager) {
   return true;
  }
  return false;

 }

}

MyCheckBoxTreeSorter.java
package com.sample;

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

public class MyCheckBoxTreeSorter extends ViewerSorter {
 @Override
 public int compare(Viewer viewer, Object left, Object right) {
  if (left instanceof Manager && right instanceof Manager) {
   return ((Manager) left).getName().compareTo(((Manager) right).getName());
  }

  if (left instanceof Manager && right instanceof Manager) {
   return ((Employee) left).getName().compareTo(((Employee) right).getName());
  }

  return 0;
 }
}

MyCheckBoxTreeViewer.java
package com.sample;

import java.util.List;

import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;

public class MyCheckBoxTreeViewer extends CheckboxTreeViewer implements ICheckStateListener, ICheckStateProvider {
 public MyCheckBoxTreeViewer(Composite parent, int style) {
  super(parent, style);
  ColumnViewerToolTipSupport.enableFor(this);
  initializeTree();
 }

 private void initializeTree() {
  setCheckStateProvider(this);
  addCheckStateListener(this);
 }

 @Override
 public boolean isChecked(Object obj) {

  if (obj instanceof Manager) {
   Manager manager = (Manager) obj;

   List<Employee> employees = manager.getEmployees();
   for (Employee emp : employees) {
    if (emp.isInOffice()) {
     return true;
    }
   }
  }

  if (obj instanceof Employee) {
   Employee emp = (Employee) obj;
   if (emp.isInOffice()) {
    return true;
   }
  }

  return false;

 }

 @Override
 public boolean isGrayed(Object obj) {
  int totalEmpsInOffice = 0;

  if (obj instanceof Manager) {
   Manager manager = (Manager) obj;

   List<Employee> employees = manager.getEmployees();
   for (Employee emp : employees) {
    if (emp.isInOffice())
     totalEmpsInOffice++;
   }

   if (totalEmpsInOffice == employees.size()) {
    return false;
   }
  }

  if (obj instanceof Employee) {
   Employee emp = (Employee) obj;
   return !emp.isInOffice();
  }

  return true;
 }

 @Override
 public void checkStateChanged(CheckStateChangedEvent event) {
  Object element = event.getElement();

  Widget item = findItem(element);

  if (!(item instanceof TreeItem)) {
   System.out.println("Given item is not an instance of tree item");
   return;
  }

  TreeItem treeItem = (TreeItem) item;
  Object obj = treeItem.getData();

  if (obj instanceof Manager) {
   System.out.println("State is changed for " + ((Manager) obj).getName());
  }

  if (obj instanceof Employee) {
   System.out.println("State is changed for " + ((Employee) obj).getName());
  }

 }

}

TestTreeViewer.java
package com.sample;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TestTreeViewer {
 private static int shellWidth = 600;
 private static int shellHeight = 600;

 private static int compositeWidth = 500;
 private static int compositeHeight = 250;

 private static void addWidgetsToShell(Display display, Shell shell) {

  Composite composite = new Composite(shell, SWT.BORDER);
  composite.setBackground(new Color(shell.getDisplay(), 102, 153, 153));
  composite.setLayout(new GridLayout());
  GridDataFactory.fillDefaults().hint(compositeWidth, compositeHeight).applyTo(composite);

  MyCheckBoxTreeContentProvider contentProvider = new MyCheckBoxTreeContentProvider();
  MyCheckBoxLabelProvider labelProvider = new MyCheckBoxLabelProvider();
  MyCheckBoxTreeSorter sorter = new MyCheckBoxTreeSorter();

  MyCheckBoxTreeViewer treeViewer = new MyCheckBoxTreeViewer(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
  GridDataFactory.fillDefaults().grab(true, true).applyTo(treeViewer.getTree());
  treeViewer.setContentProvider(contentProvider);
  treeViewer.setLabelProvider(labelProvider);
  treeViewer.setSorter(sorter);
  treeViewer.setAutoExpandLevel(2);
  treeViewer.setInput("root");

 }

 public static void main(String[] args) {

  /* Instantiate Display object, it represents SWT session */
  Display display = new Display();

  /*
   * Define Shell, it represent a window, You can add more than one shell
   * to Display
   */
  Shell shell = new Shell(display);
  shell.setSize(shellWidth, shellHeight);
  shell.setLayout(new GridLayout());

  addWidgetsToShell(display, shell);

  /* Open shell window */
  shell.open();

  /*
   * Run the event dispatching loop until an exit condition occurs, which
   * is typically when the main shell window is closed by the user.
   */

  while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
    display.sleep();
  }

  /* Dispose the display */
  display.dispose();
 }

}

Run ‘TestTreeViewer.java’, you can able to see following kind of tree.















Previous                                                 Next                                                 Home

1 comment: