diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/ContainerCheckedTreeViewer.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/ContainerCheckedTreeViewer.java index 820a26e..fd7db29 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/ContainerCheckedTreeViewer.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/dialogs/ContainerCheckedTreeViewer.java @@ -17,6 +17,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.Set; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ITreeViewerListener; import org.eclipse.jface.viewers.TreeExpansionEvent; @@ -176,6 +177,7 @@ } } + // avoid accessing the widget, if there are no updates boolean updated = false; boolean checked = item.getChecked(); @@ -209,27 +211,49 @@ @Override public void setCheckedElements(Object[] elements) { Object[] oldCheckedElements = getCheckedElements(); - super.setCheckedElements(elements); + HashSet elementsToCheck = new HashSet<>(); + HashSet elementsToUncheck = new HashSet<>(Arrays.asList(oldCheckedElements)); + for (Object element : elements) { + if (!elementsToUncheck.remove(element)) { + elementsToCheck.add(element); + } + } + + for (Object elementToCheck : elementsToCheck) { + super.setChecked(elementToCheck, true); + } + for (Object elementToUncheck : elementsToUncheck) { + super.setChecked(elementToUncheck, false); + } + + if (elementsToCheck.isEmpty() && elementsToUncheck.isEmpty()) { + return; // noting changed + } Control tree = getControl(); try { tree.setRedraw(false); - if (oldCheckedElements.length > 0) { - // calculate intersection of previously and newly checked elements to avoid - // no-op updates - HashSet changedElements = new HashSet<>(Arrays.asList(elements)); - for (Object element : oldCheckedElements) { - changedElements.remove(element); - } - doCheckStateChanged(changedElements.toArray()); - } else { - doCheckStateChanged(elements); + if (!elementsToCheck.isEmpty()) { + doCheckStateChanged(elementsToCheck.toArray()); + } + + if (!elementsToUncheck.isEmpty()) { + updateElementsState(elementsToUncheck); } } finally { tree.setRedraw(true); } } + private void updateElementsState(Set elementsToUpdate) { + for (Object element : elementsToUpdate) { + Widget item = findItem(element); + if (item instanceof TreeItem) { + updateParentItems((TreeItem) item); + } + } + } + @Override public boolean setSubtreeChecked(Object element, boolean state) { if (super.setSubtreeChecked(element, state)) {