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: The grayed state is used to visualize the checked
19 * state of its children. Containers are checked and non-gary if all contained
20 * leafs are checked. The container is grayed if some but not all leafs are
23 public class ContainerCheckedTreeViewer extends CheckboxTreeViewer {
26 * Constructor for ContainerCheckedTreeViewer.
28 * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite)
30 public ContainerCheckedTreeViewer(Composite parent) {
36 * Constructor for ContainerCheckedTreeViewer.
38 * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite,int)
40 public ContainerCheckedTreeViewer(Composite parent, int style) {
46 * Constructor for ContainerCheckedTreeViewer.
48 * @see CheckboxTreeViewer#CheckboxTreeViewer(Tree)
50 public ContainerCheckedTreeViewer(Tree tree) {
55 private void initViewer() {
56 setUseHashlookup(true);
57 addCheckStateListener(new ICheckStateListener() {
58 public void checkStateChanged(CheckStateChangedEvent event) {
59 doCheckStateChanged(event.getElement());
62 addTreeListener(new ITreeViewerListener() {
63 public void treeCollapsed(TreeExpansionEvent event) {
66 public void treeExpanded(TreeExpansionEvent event) {
67 Widget item = findItem(event.getElement());
68 if (item instanceof TreeItem) {
69 initializeItem((TreeItem) item);
75 protected void doCheckStateChanged(Object element) {
76 Widget item = findItem(element);
77 if (item instanceof TreeItem) {
78 TreeItem treeItem = (TreeItem) item;
79 treeItem.setGrayed(false);
80 updateChildrenItems(treeItem);
81 updateParentItems(treeItem.getParentItem());
86 * The item has expanded. Updates the checked state of its children.
88 private void initializeItem(TreeItem item) {
89 if (item.getChecked() && !item.getGrayed()) {
90 updateChildrenItems((TreeItem) item);
95 * Updates the check state of all created children
97 private void updateChildrenItems(TreeItem parent) {
98 Item[] children = getChildren(parent);
99 boolean state = parent.getChecked();
100 for (int i = 0; i < children.length; i++) {
101 TreeItem curr = (TreeItem) children[i];
102 if (curr.getData() != null
103 && ((curr.getChecked() != state) || curr.getGrayed())) {
104 curr.setChecked(state);
105 curr.setGrayed(false);
106 updateChildrenItems(curr);
112 * Updates the check / gray state of all parent items
114 private void updateParentItems(TreeItem item) {
116 Item[] children = getChildren(item);
117 boolean containsChecked = false;
118 boolean containsUnchecked = false;
119 for (int i = 0; i < children.length; i++) {
120 TreeItem curr = (TreeItem) children[i];
121 containsChecked |= curr.getChecked();
122 containsUnchecked |= (!curr.getChecked() || curr.getGrayed());
124 item.setChecked(containsChecked);
125 item.setGrayed(containsChecked && containsUnchecked);
126 updateParentItems(item.getParentItem());
130 public boolean setChecked(Object element, boolean state) {
131 if (super.setChecked(element, state)) {
132 doCheckStateChanged(element);
138 public void setCheckedElements(Object[] elements) {
139 super.setCheckedElements(elements);
140 for (int i = 0; i < elements.length; i++) {
141 doCheckStateChanged(elements[i]);
145 protected void setExpanded(Item item, boolean expand) {
146 super.setExpanded(item, expand);
147 if (expand && item instanceof TreeItem) {
148 initializeItem((TreeItem) item);
152 public Object[] getCheckedElements() {
153 Object[] checked = super.getCheckedElements();
154 // add all items that are children of a checked node but not created yet
155 ArrayList result = new ArrayList();
156 for (int i = 0; i < checked.length; i++) {
157 Object curr = checked[i];
159 Widget item = findItem(curr);
161 Item[] children = getChildren(item);
162 // check if contains the dummy node
163 if (children.length == 1 && children[0].getData() == null) {
165 collectChildren(curr, result);
169 return result.toArray();
172 private void collectChildren(Object element, ArrayList result) {
173 Object[] filteredChildren = getFilteredChildren(element);
174 for (int i = 0; i < filteredChildren.length; i++) {
175 Object curr = filteredChildren[i];
177 collectChildren(curr, result);