Source code: org/eclipse/jface/viewers/TreeViewer.java
1 /*******************************************************************************
2 * Copyright (c) 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11
12 package org.eclipse.jface.viewers;
13
14 import java.util.Iterator;
15 import java.util.List;
16
17 import org.eclipse.jface.util.Assert;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.events.TreeListener;
20 import org.eclipse.swt.graphics.Image;
21 import org.eclipse.swt.graphics.Point;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Item;
25 import org.eclipse.swt.widgets.Tree;
26 import org.eclipse.swt.widgets.TreeItem;
27 import org.eclipse.swt.widgets.Widget;
28
29 /**
30 * A concrete viewer based on an SWT <code>Tree</code> control.
31 * <p>
32 * This class is not intended to be subclassed outside the viewer framework.
33 * It is designed to be instantiated with a pre-existing SWT tree control and configured
34 * with a domain-specific content provider, label provider, element filter (optional),
35 * and element sorter (optional).
36 * </p>
37 * <p>
38 * Content providers for tree viewers must implement the <code>ITreeContentProvider</code>
39 * interface.
40 * </p>
41 */
42 public class TreeViewer extends AbstractTreeViewer {
43
44 /**
45 * This viewer's control.
46 */
47 private Tree tree;
48 /**
49 * Creates a tree viewer on a newly-created tree control under the given parent.
50 * The tree control is created using the SWT style bits <code>MULTI, H_SCROLL, V_SCROLL,</code> and <code>BORDER</code>.
51 * The viewer has no input, no content provider, a default label provider,
52 * no sorter, and no filters.
53 *
54 * @param parent the parent control
55 */
56 public TreeViewer(Composite parent) {
57 this(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
58 }
59 /**
60 * Creates a tree viewer on a newly-created tree control under the given parent.
61 * The tree control is created using the given SWT style bits.
62 * The viewer has no input, no content provider, a default label provider,
63 * no sorter, and no filters.
64 *
65 * @param parent the parent control
66 * @param style the SWT style bits used to create the tree.
67 */
68 public TreeViewer(Composite parent, int style) {
69 this(new Tree(parent, style));
70 }
71 /**
72 * Creates a tree viewer on the given tree control.
73 * The viewer has no input, no content provider, a default label provider,
74 * no sorter, and no filters.
75 *
76 * @param tree the tree control
77 */
78 public TreeViewer(Tree tree) {
79 super();
80 this.tree = tree;
81 hookControl(tree);
82 }
83 /* (non-Javadoc)
84 * Method declared in AbstractTreeViewer.
85 */
86 protected void addTreeListener(Control c, TreeListener listener) {
87 ((Tree)c).addTreeListener(listener);
88 }
89 /* (non-Javadoc)
90 * Method declared in AbstractTreeViewer.
91 */
92 protected void doUpdateItem(final Item item, Object element) {
93
94 if(item.isDisposed()){
95 unmapElement(element);
96 Assert.isTrue(!item.isDisposed(),"Update to disposed element " + element.toString());//$NON-NLS-1$
97 return;
98 }
99
100 // update icon and label
101 IBaseLabelProvider baseProvider = getLabelProvider();
102 if (baseProvider instanceof IViewerLabelProvider) {
103 IViewerLabelProvider provider = (IViewerLabelProvider)baseProvider;
104
105 ViewerLabel updateLabel = new ViewerLabel(item.getText(), item.getImage());
106 provider.updateLabel(updateLabel, element);
107
108 if(updateLabel.hasNewImage())
109 item.setImage(updateLabel.getImage());
110 if(updateLabel.hasNewText())
111 item.setText(updateLabel.getText());
112
113 } else {
114 if(baseProvider instanceof ILabelProvider){
115 ILabelProvider provider = (ILabelProvider)baseProvider;
116 item.setText(provider.getText(element));
117 Image image = provider.getImage(element);
118 if (item.getImage() != image)
119 item.setImage(image);
120 }
121 }
122 if (baseProvider instanceof IColorProvider) {
123 IColorProvider cp = (IColorProvider) baseProvider;
124 TreeItem treeItem = (TreeItem) item;
125 treeItem.setForeground(cp.getForeground(element));
126 treeItem.setBackground(cp.getBackground(element));
127 }
128 if (baseProvider instanceof IFontProvider) {
129 IFontProvider fprov = (IFontProvider) baseProvider;
130 TreeItem treeItem = (TreeItem) item;
131 treeItem.setFont(fprov.getFont(element));
132 }
133 }
134 /* (non-Javadoc)
135 * Method declared in AbstractTreeViewer.
136 */
137 protected Item[] getChildren(Widget o) {
138 if (o instanceof TreeItem)
139 return ((TreeItem) o).getItems();
140 if (o instanceof Tree)
141 return ((Tree) o).getItems();
142 return null;
143 }
144 /* (non-Javadoc)
145 * Method declared in Viewer.
146 */
147 public Control getControl() {
148 return tree;
149 }
150 /* (non-Javadoc)
151 * Method declared in AbstractTreeViewer.
152 */
153 protected boolean getExpanded(Item item) {
154 return ((TreeItem) item).getExpanded();
155 }
156 /* (non-Javadoc)
157 * Method declared in StructuredViewer.
158 */
159 protected Item getItem(int x, int y) {
160 return getTree().getItem(getTree().toControl(new Point(x, y)));
161 }
162 /* (non-Javadoc)
163 * Method declared in AbstractTreeViewer.
164 */
165 protected int getItemCount(Control widget) {
166 return ((Tree) widget).getItemCount();
167 }
168 /* (non-Javadoc)
169 * Method declared in AbstractTreeViewer.
170 */
171 protected int getItemCount(Item item) {
172 return ((TreeItem) item).getItemCount();
173 }
174 /* (non-Javadoc)
175 * Method declared in AbstractTreeViewer.
176 */
177 protected Item[] getItems(Item item) {
178 return ((TreeItem) item).getItems();
179 }
180 /**
181 * The tree viewer implementation of this <code>Viewer</code> framework
182 * method returns the label provider, which in the case of tree
183 * viewers will be an instance of <code>ILabelProvider</code>.
184 */
185 public IBaseLabelProvider getLabelProvider() {
186 return super.getLabelProvider();
187 }
188 /* (non-Javadoc)
189 * Method declared in AbstractTreeViewer.
190 */
191 protected Item getParentItem(Item item) {
192 return ((TreeItem)item).getParentItem();
193 }
194 /* (non-Javadoc)
195 * Method declared in AbstractTreeViewer.
196 */
197 protected Item[] getSelection(Control widget) {
198 return ((Tree) widget).getSelection();
199 }
200 /**
201 * Returns this tree viewer's tree control.
202 *
203 * @return the tree control
204 */
205 public Tree getTree() {
206 return tree;
207 }
208 /* (non-Javadoc)
209 * Method declared in AbstractTreeViewer.
210 */
211 protected Item newItem(Widget parent, int flags, int ix) {
212 TreeItem item;
213 if (ix >= 0) {
214 if (parent instanceof TreeItem)
215 item = new TreeItem((TreeItem) parent, flags, ix);
216 else
217 item = new TreeItem((Tree) parent, flags, ix);
218 } else {
219 if (parent instanceof TreeItem)
220 item = new TreeItem((TreeItem) parent, flags);
221 else
222 item = new TreeItem((Tree) parent, flags);
223 }
224 return item;
225 }
226 /* (non-Javadoc)
227 * Method declared in AbstractTreeViewer.
228 */
229 protected void removeAll(Control widget) {
230 ((Tree) widget).removeAll();
231 }
232 /* (non-Javadoc)
233 * Method declared in AbstractTreeViewer.
234 */
235 protected void setExpanded(Item node, boolean expand) {
236 ((TreeItem) node).setExpanded(expand);
237 }
238 /**
239 * The tree viewer implementation of this <code>Viewer</code> framework
240 * method ensures that the given label provider is an instance
241 * of <code>ILabelProvider</code>.
242 */
243 public void setLabelProvider(IBaseLabelProvider labelProvider) {
244 Assert.isTrue(labelProvider instanceof ILabelProvider);
245 super.setLabelProvider(labelProvider);
246 }
247 /* (non-Javadoc)
248 * Method declared in AbstractTreeViewer.
249 */
250 protected void setSelection(List items) {
251
252 Item[] current = getSelection(getTree());
253
254 //Don't bother resetting the same selection
255 if(haveSameData(items,current))
256 return;
257
258 TreeItem[] newItems = new TreeItem[items.size()];
259 items.toArray(newItems);
260 getTree().setSelection(newItems);
261 }
262
263 /**
264 * Returns <code>true</code> if the given list and array of items
265 * refer to the same model elements. Order is unimportant.
266 *
267 * @param items the list of items
268 * @param current the array of items
269 * @return <code>true</code> if the refer to the same elements, <code>false</code> otherwise
270 */
271 private boolean haveSameData(List items, Item[] current){
272 //If they are not the same size then they are not equivalent
273 int n = items.size();
274 if (n != current.length)
275 return false;
276
277 CustomHashtable itemSet = newHashtable(n*2+1);
278 for (Iterator i = items.iterator(); i.hasNext();) {
279 Item item = (Item) i.next();
280 Object element = item.getData();
281 itemSet.put(element, element);
282 }
283
284 //Go through the items of the current collection
285 //If there is a mismatch return false
286 for (int i = 0; i < current.length; i++) {
287 if (!itemSet.containsKey(current[i].getData()))
288 return false;
289 }
290
291 return true;
292 }
293 /* (non-Javadoc)
294 * Method declared in AbstractTreeViewer.
295 */
296 protected void showItem(Item item) {
297 getTree().showItem((TreeItem)item);
298 }
299 }