Skip to main content
summaryrefslogtreecommitdiffstats
blob: b23dff6c03bf9b9b93ecf8ea6d09209daf980b8c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
package org.eclipse.swt.widgets;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import java.util.*;

/*
 * Licensed Materials - Property of IBM,
 * (c) Copyright IBM Corp. 1998, 2000  All Rights Reserved
 */
 
/** 
 * This class stores and manages child items of a tree item.
 * It provides protocol to query the index of an item relative 
 * to the root and to retrieve items by index.
 * The TreeItem class implements this protocol for general
 * tree items.
 * TreeRoots provides a special implementation that allows the 
 * Tree class to treat trees with one root and with multiple 
 * roots equally.
 */
abstract class AbstractTreeItem extends SelectableItem {
	private Vector children;
	private boolean isExpanded = false;		
	// number of children. 
	// includes all expanded items down to the leafs.
	private int visibleItemCount = 0;

/**
 * Create a new instance of the receiver.
 * @param parent - widget the receiver belongs to
 * @param swtStyle - widget style. see Widget class for details
 */
AbstractTreeItem(Tree parent, int swtStyle) {
	super(parent, swtStyle);
}
/**
 * Insert 'item' in the list of child items. Notify the 
 * parent about the new item.
 * @param 'item' - the item that should be added to the 
 *	receiver's children.
 * @param index - position that 'item' will be inserted at
 *	in the receiver.
 */
void add(TreeItem item, int index) {
	Vector items = getChildren();
	int visibleIndex = getVisibleIndex();
	
	if (index < 0 || index > items.size()) {
		error(SWT.ERROR_INVALID_RANGE);
	}
	if (item.isRoot()) {
		visibleIndex = index;
	}
	else
	if (isExpanded == false) {
		visibleIndex = -1;
	}
	if (visibleIndex != -1) {
		if (index > 0) {
			TreeItem previousChild = (TreeItem) getChildren().elementAt(index - 1);
			visibleIndex = previousChild.getVisibleIndex() + previousChild.getVisibleItemCount() + 1;
		}
		else {
			 visibleIndex = getVisibleIndex() + 1;
		}
	}
	getSelectableParent().addingItem(item, visibleIndex);
	item.setIndex(index);
	resetChildIndices(index, true);
	items.insertElementAt(item, index);
	if (isExpanded == true) {
		visibleItemCount++;
		calculateVisibleItemCountParent();
	}
	getSelectableParent().addedItem(item, visibleIndex);
}
/** 
 * Set whether the receiver is expanded or not. 
 * If the receiver is expanded its child items are visible.
 * @param expanded - 
 *	true=the receiver is expanded, making its child items visible.
 * 	false=the receiver is collapsed, making its child items invisible 
 */
void internalSetExpanded(boolean expanded) {
	isExpanded = expanded;
	calculateVisibleItemCount();
}
/**
 * Calculate the number of expanded children.
 * Recurse up in the tree to the root item.
 */
abstract void calculateVisibleItemCount();
/**
 * Calculate the number of expanded children for the parent item
 * of this item.
 */
abstract void calculateVisibleItemCountParent();
/**
 * Deselect the receiver and all children
 */
void deselectAll() {
	Enumeration children = getChildren().elements();
	AbstractTreeItem treeItem;

	setSelected(false);
	while (children.hasMoreElements() == true) {
		treeItem = (AbstractTreeItem) children.nextElement();
		treeItem.deselectAll();
	}
}
/** 
 * Destroy all children of the receiver	
 */
void disposeItem() {
	Vector children = getChildren();
	AbstractTreeItem child;
	while (children.size() > 0) {		// TreeItem objects are removed from vector during dispose
		child = (AbstractTreeItem) children.firstElement();
		child.dispose();
	}
	doDispose();
	super.disposeItem();
}
/**
 * Subclasses should free resources here
 */
void doDispose() {
	setChildren(null);
	visibleItemCount = 0;
}
/**
 * Answer the Vector containing the child items of the receiver.
 */
Vector getChildren() {
	if (children == null) {
		children = new Vector(4);
	}
	return children;
}
/**
 * Answer whether the receiver is expanded or not. 
 * If the receiver is expanded its children are visible.
 * @return 
 *	true - the receiver is expanded, making its children visible
 * 	false - the receiver is collapsed, making its children invisible 
 */
public boolean getExpanded() {
	if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
	if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);

	return isExpanded;
}
/**
 * Answer the number of children.
 */
public int getItemCount() {
	if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
	if (!isValidWidget ()) error (SWT.ERROR_WIDGET_DISPOSED);

	return getChildren().size();
}
/**
 * Answer the index of the receiver relative to the first root 
 * item.
 * If 'anIndex' is the global index of the expanded item 'anItem' 
 * then the following expressions are true:
 * 'anItem  == theRoot.getVisibleItem(anIndex)' and
 * 'anIndex == anItem.getVisibleIndex()'
 * @return
 *	The index of the receiver relative to the first root item.
 *	Answer -1 if the receiver is not visible (because the parent 
 *	is collapsed).
 */
abstract int getVisibleIndex();
/**
 * Answer the index of the child item identified by 'childIndex' 
 * relative to the first root item.
 */
abstract int getVisibleIndex(int childIndex);
/**
 * Answer the item at 'searchIndex' relativ to the receiver.
 * When this method is called for the root item, 'searchIndex' 
 * represents the global index into all items of the tree.
 * searchIndex=0 returns the receiver. 
 * searchIndex=1 returns the first visible child.
 * Note: searchIndex must be >= 0
 *
 * Note: 
 * Visible in this context does not neccessarily mean that the 
 * item is displayed on the screen. Visible here means that all 
 * the parents of the item are expanded. An item is only 
 * visible on screen if it is within the receiver's parent's 
 * client area.
 */
abstract TreeItem getVisibleItem(int searchIndex);
/**
 * Answer the number of expanded children, direct and indirect.
 */
int getVisibleItemCount() {
	return visibleItemCount;
}
/**
 * Returns the expanded state. Circumvent widget/thread check 
 * for performance. For non-API callers only.
 */
boolean internalGetExpanded() {
	return isExpanded;
}
/**
 * Answer whether the receiver is a leaf item.
 * An item is a leaf when it has no child items.
 * @return
 *	true - receiver is a leaf item
 *	false - receiver is not a leaf item.
 */
boolean isLeaf() {
	return (getChildren().size() == 0);
}
/**
 * Answer whether the receiver is a root item.
 * The receiver is a root item when it doesn't have a parent item.
 * @return 
 *	true - the receiver is a root item.
 * 	false - the receiver is not a root item.
 */
boolean isRoot() {
	return false;
}
/** 
 * Remove 'child' from the receiver. 
 * Notify the parent widget only if it is not being disposed itself.
 */
void removeItem(SelectableItem child) {
	Vector children = getChildren();
	SelectableItemWidget parent = getSelectableParent();
	int childIndex = children.indexOf(child);

	if (childIndex != -1) {
		if (((Tree) parent).isRemovingAll() == true) {
			children.removeElementAt(childIndex);		// just remove the item from the list if the whole tree is being disposed
			if (isExpanded == true) {
				visibleItemCount--;
				calculateVisibleItemCountParent();
			}
		}
		else {
			parent.removingItem(child);	
			children.removeElementAt(childIndex);
			if (isExpanded == true) {
				visibleItemCount--;
				calculateVisibleItemCountParent();
			}
			resetChildIndices(childIndex, false);						// mark child index dirty
			parent.removedItem(child);
		}
	}
}
/**
 * Allow subclasses to reset any cached data.
 * Called for all children of the receiver.
 */
void reset() {
	Enumeration children = getChildren().elements();
	AbstractTreeItem treeItem;

	while (children.hasMoreElements() == true) {
		treeItem = (AbstractTreeItem) children.nextElement();
		treeItem.reset();
	}
}
/**
 * Mark all child indices dirty starting with the child at 
 * 'startIndex'. This causes getIndex to recalculate the index.
 * @param startIndex - index in the list of children at which 
 *	and after which the indices are reset.
 */
void resetChildIndices(int startIndex, boolean addItem) {
	Vector children = getChildren();
	TreeItem child;
	int increment = addItem ? 1 : 0;

	for (int i = startIndex; i < children.size(); i++) {
		child = (TreeItem) children.elementAt(i);
		child.setIndex(i + increment);								// mark child index dirty
	}
}
/**
 * Select the receiver and all children.
 * Return a Vector containing all the items that have been selected 
 * (and that have not been selected before).
 */
Vector selectAll(Vector selectedItems) {
	Enumeration children = getChildren().elements();
	AbstractTreeItem treeItem;

	if (isSelected() == false) {
		selectedItems.addElement(this);
		setSelected(true);
		getSelectableParent().redrawSelection(this);
	}
	while (children.hasMoreElements() == true) {
		treeItem = (AbstractTreeItem) children.nextElement();
		selectedItems = treeItem.selectAll(selectedItems);
	}
	return selectedItems;
}
/**
 * Set the Array containing the receiver's child items to 'children'.
 */
void setChildren(Vector children) {
	this.children = children;
}

void setVisibleItemCount(int count) {
	visibleItemCount = count;
}
}

Back to the top