1 package net.sourceforge.phpdt.internal.ui.viewsupport;
3 import java.util.ArrayList;
5 import org.eclipse.jface.viewers.CheckStateChangedEvent;
6 import org.eclipse.jface.viewers.CheckboxTreeViewer;
7 import org.eclipse.jface.viewers.ICheckStateListener;
8 import org.eclipse.jface.viewers.ITreeViewerListener;
9 import org.eclipse.jface.viewers.TreeExpansionEvent;
10 import org.eclipse.swt.widgets.Composite;
11 import org.eclipse.swt.widgets.Item;
12 import org.eclipse.swt.widgets.Tree;
13 import org.eclipse.swt.widgets.TreeItem;
14 import org.eclipse.swt.widgets.Widget;
17 * CheckboxTreeViewer with special behaviour of the checked / gray state on
18 * container (non-leaf) nodes:
19 * The grayed state is used to visualize the checked state of its children.
20 * Containers are checked and non-gary if all contained leafs are checked. The
21 * container is grayed if some but not all leafs are checked.
23 public class ContainerCheckedTreeViewer extends CheckboxTreeViewer {
26 * Constructor for ContainerCheckedTreeViewer.
27 * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite)
29 public ContainerCheckedTreeViewer(Composite parent) {
35 * Constructor for ContainerCheckedTreeViewer.
36 * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite,int)
38 public ContainerCheckedTreeViewer(Composite parent, int style) {
44 * Constructor for ContainerCheckedTreeViewer.
45 * @see CheckboxTreeViewer#CheckboxTreeViewer(Tree)
47 public ContainerCheckedTreeViewer(Tree tree) {
52 private void initViewer() {
53 setUseHashlookup(true);
54 addCheckStateListener(new ICheckStateListener() {
55 public void checkStateChanged(CheckStateChangedEvent event) {
56 doCheckStateChanged(event.getElement());
59 addTreeListener(new ITreeViewerListener() {
60 public void treeCollapsed(TreeExpansionEvent event) {}
61 public void treeExpanded(TreeExpansionEvent event) {
62 Widget item = findItem(event.getElement());
63 if (item instanceof TreeItem) {
64 initializeItem((TreeItem) item);
70 protected void doCheckStateChanged(Object element) {
71 Widget item = findItem(element);
72 if (item instanceof TreeItem) {
73 TreeItem treeItem = (TreeItem) item;
74 treeItem.setGrayed(false);
75 updateChildrenItems(treeItem);
76 updateParentItems(treeItem.getParentItem());
81 * The item has expanded. Updates the checked state of its children.
83 private void initializeItem(TreeItem item) {
84 if (item.getChecked() && !item.getGrayed()) {
85 updateChildrenItems((TreeItem) item);
90 * Updates the check state of all created children
92 private void updateChildrenItems(TreeItem parent) {
93 Item[] children = getChildren(parent);
94 boolean state = parent.getChecked();
95 for (int i = 0; i < children.length; i++) {
96 TreeItem curr = (TreeItem) children[i];
97 if (curr.getData() != null && ((curr.getChecked() != state) || curr.getGrayed())) {
98 curr.setChecked(state);
99 curr.setGrayed(false);
100 updateChildrenItems(curr);
106 * Updates the check / gray state of all parent items
108 private void updateParentItems(TreeItem item) {
110 Item[] children = getChildren(item);
111 boolean containsChecked = false;
112 boolean containsUnchecked = false;
113 for (int i = 0; i < children.length; i++) {
114 TreeItem curr = (TreeItem) children[i];
115 containsChecked |= curr.getChecked();
116 containsUnchecked |= (!curr.getChecked() || curr.getGrayed());
118 item.setChecked(containsChecked);
119 item.setGrayed(containsChecked && containsUnchecked);
120 updateParentItems(item.getParentItem());
124 public boolean setChecked(Object element, boolean state) {
125 if (super.setChecked(element, state)) {
126 doCheckStateChanged(element);
132 public void setCheckedElements(Object[] elements) {
133 super.setCheckedElements(elements);
134 for (int i = 0; i < elements.length; i++) {
135 doCheckStateChanged(elements[i]);
139 protected void setExpanded(Item item, boolean expand) {
140 super.setExpanded(item, expand);
141 if (expand && item instanceof TreeItem) {
142 initializeItem((TreeItem) item);
146 public Object[] getCheckedElements() {
147 Object[] checked = super.getCheckedElements();
148 // add all items that are children of a checked node but not created yet
149 ArrayList result = new ArrayList();
150 for (int i = 0; i < checked.length; i++) {
151 Object curr = checked[i];
153 Widget item = findItem(curr);
155 Item[] children = getChildren(item);
156 // check if contains the dummy node
157 if (children.length == 1 && children[0].getData() == null) {
159 collectChildren(curr, result);
163 return result.toArray();
166 private void collectChildren(Object element, ArrayList result) {
167 Object[] filteredChildren = getFilteredChildren(element);
168 for (int i = 0; i < filteredChildren.length; i++) {
169 Object curr = filteredChildren[i];
171 collectChildren(curr, result);