*/
private void updateChildren(Widget widget, Object parent,
Object[] elementChildren, boolean updateLabels) {
// optimization! prune collapsed subtrees
if (widget instanceof Item) {
Item ti = (Item) widget;
if (!getExpanded(ti)) {
if (optionallyPruneChildren(ti, parent)) {
// children were pruned, nothing left to do
return;
}
// The following code is being executed if children were not pruned.
// This is (as of 3.5) only the case for CheckboxTreeViewer.
Item[] its = getItems(ti);
if (isExpandable(ti, null, parent)) {
if (its.length == 0) {
// need dummy node
newItem(ti, SWT.NULL, -1);
return;
} else if (its.length == 1 && its[0].getData() == null) {
// dummy node exists, nothing left to do
return;
}
// else fall through to normal update code below
} else {
for (int i = 0; i < its.length; i++) {
if (its[i].getData() != null) {
disassociate(its[i]);
}
its[i].dispose();
}
// nothing left to do
return;
}
}
}
// If the children weren't passed in, get them now since they're needed
// below.
if (elementChildren == null) {
if (isTreePathContentProvider() && widget instanceof Item) {
TreePath path = getTreePathFromItem((Item) widget);
elementChildren = getSortedChildren(path);
} else {
elementChildren = getSortedChildren(parent);
}
}
Control tree = getControl();
// WORKAROUND
int oldCnt = -1;
if (widget == tree) {
oldCnt = getItemCount(tree);
}
Item[] items = getChildren(widget);
// save the expanded elements
CustomHashtable expanded = newHashtable(CustomHashtable.DEFAULT_CAPACITY); // assume
// num
// expanded
// is
// small
for (int i = 0; i < items.length; ++i) {
if (getExpanded(items[i])) {
Object element = items[i].getData();
if (element != null) {
expanded.put(element, element);
}
}
}
int min = Math.min(elementChildren.length, items.length);
// dispose of surplus items, optimizing for the case where elements have
// been deleted but not reordered, or all elements have been removed.
int numItemsToDispose = items.length - min;
if (numItemsToDispose > 0) {
CustomHashtable children = newHashtable(elementChildren.length * 2);
for (int i = 0; i < elementChildren.length; i++) {
Object elementChild = elementChildren[i];
children.put(elementChild, elementChild);
}
int i = 0;
while (numItemsToDispose > 0 && i < items.length) {
Object data = items[i].getData();
if (data == null || !children.containsKey(data)) {
if (data != null) {
disassociate(items[i]);
}
items[i].dispose();
if (i + 1 < items.length) {
// The components at positions i+1 through
// items.length-1 in the source array are copied into
// positions i through items.length-2
System.arraycopy(items, i + 1, items, i, items.length - (i+1));
}
numItemsToDispose--;
} else {
i++;
}
}
}
// compare first min items, and update item if necessary
// need to do it in two passes:
// 1: disassociate old items
// 2: associate new items
// because otherwise a later disassociate can remove a mapping made for
// a previous associate,
// making the map inconsistent
for (int i = 0; i < min; ++i) {
Item item = items[i];
Object oldElement = item.getData();
if (oldElement != null) {
Object newElement = elementChildren[i];
if (newElement != oldElement) {
if (equals(newElement, oldElement)) {
// update the data to be the new element, since
// although the elements
// may be equal, they may still have different labels
// or children
Object data = item.getData();
if (data != null) {
unmapElement(data, item);
}
item.setData(newElement);
mapElement(newElement, item);
} else {
disassociate(item);
// Clear the text and image to force a label update
item.setImage(null);
item.setText("");//$NON-NLS-1$
}
}
}
}
for (int i = 0; i < min; ++i) {
Item item = items[i];
Object newElement = elementChildren[i];
if (item.getData() == null) {
// old and new elements are not equal
associate(newElement, item);
updatePlus(item, newElement);
updateItem(item, newElement);
} else {
// old and new elements are equal
updatePlus(item, newElement);
if (updateLabels) {
updateItem(item, newElement);
}
}
}
// Restore expanded state for items that changed position.
// Make sure setExpanded is called after updatePlus, since
// setExpanded(false) fails if item has no children.
// Need to call setExpanded for both expanded and unexpanded
// cases since the expanded state can change either way.
// This needs to be done in a second loop, see bug 148025.
for (int i = 0; i < min; ++i) {
Item item = items[i];
Object newElement = elementChildren[i];
setExpanded(item, expanded.containsKey(newElement));
}
// add any remaining elements