1 11 package org.eclipse.ui.internal.ide.dialogs; 12 13 import java.util.ArrayList ; 14 import java.util.Collection ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.commands.common.EventManager; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.core.runtime.IProgressMonitor; 25 import org.eclipse.core.runtime.Path; 26 import org.eclipse.core.runtime.SafeRunner; 27 import org.eclipse.jface.util.SafeRunnable; 28 import org.eclipse.jface.viewers.CheckStateChangedEvent; 29 import org.eclipse.jface.viewers.CheckboxTableViewer; 30 import org.eclipse.jface.viewers.CheckboxTreeViewer; 31 import org.eclipse.jface.viewers.ICheckStateListener; 32 import org.eclipse.jface.viewers.ILabelProvider; 33 import org.eclipse.jface.viewers.ISelectionChangedListener; 34 import org.eclipse.jface.viewers.IStructuredContentProvider; 35 import org.eclipse.jface.viewers.IStructuredSelection; 36 import org.eclipse.jface.viewers.ITreeContentProvider; 37 import org.eclipse.jface.viewers.ITreeViewerListener; 38 import org.eclipse.jface.viewers.SelectionChangedEvent; 39 import org.eclipse.jface.viewers.StructuredSelection; 40 import org.eclipse.jface.viewers.TreeExpansionEvent; 41 import org.eclipse.jface.viewers.ViewerComparator; 42 import org.eclipse.swt.SWT; 43 import org.eclipse.swt.custom.BusyIndicator; 44 import org.eclipse.swt.layout.GridData; 45 import org.eclipse.swt.layout.GridLayout; 46 import org.eclipse.swt.widgets.Composite; 47 import org.eclipse.swt.widgets.Table; 48 import org.eclipse.swt.widgets.Tree; 49 50 54 public class ResourceTreeAndListGroup extends EventManager implements 55 ICheckStateListener, ISelectionChangedListener, ITreeViewerListener { 56 private Object root; 57 58 private Object currentTreeSelection; 59 60 private Collection expandedTreeNodes = new HashSet (); 61 62 private Map checkedStateStore = new HashMap (9); 63 64 private Collection whiteCheckedTreeItems = new HashSet (); 65 66 private ITreeContentProvider treeContentProvider; 67 68 private IStructuredContentProvider listContentProvider; 69 70 private ILabelProvider treeLabelProvider; 71 72 private ILabelProvider listLabelProvider; 73 74 private CheckboxTreeViewer treeViewer; 76 77 private CheckboxTableViewer listViewer; 78 79 private static int PREFERRED_HEIGHT = 150; 81 82 98 public ResourceTreeAndListGroup(Composite parent, Object rootObject, 99 ITreeContentProvider treeContentProvider, 100 ILabelProvider treeLabelProvider, 101 IStructuredContentProvider listContentProvider, 102 ILabelProvider listLabelProvider, int style, boolean useHeightHint) { 103 104 root = rootObject; 105 this.treeContentProvider = treeContentProvider; 106 this.listContentProvider = listContentProvider; 107 this.treeLabelProvider = treeLabelProvider; 108 this.listLabelProvider = listLabelProvider; 109 createContents(parent, style, useHeightHint); 110 } 111 112 115 public void aboutToOpen() { 116 determineWhiteCheckedDescendents(root); 117 checkNewTreeElements(treeContentProvider.getElements(root)); 118 currentTreeSelection = null; 119 120 Object [] elements = treeContentProvider.getElements(root); 122 Object primary = elements.length > 0 ? elements[0] : null; 123 if (primary != null) { 124 treeViewer.setSelection(new StructuredSelection(primary)); 125 } 126 treeViewer.getControl().setFocus(); 127 } 128 129 135 public void addCheckStateListener(ICheckStateListener listener) { 136 addListenerObject(listener); 137 } 138 139 146 protected boolean areAllChildrenWhiteChecked(Object treeElement) { 147 Object [] children = treeContentProvider.getChildren(treeElement); 148 for (int i = 0; i < children.length; ++i) { 149 if (!whiteCheckedTreeItems.contains(children[i])) { 150 return false; 151 } 152 } 153 154 return true; 155 } 156 157 164 protected boolean areAllElementsChecked(Object treeElement) { 165 List checkedElements = (List ) checkedStateStore.get(treeElement); 166 if (checkedElements == null) { 167 return false; 168 } 169 170 return getListItemsSize(treeElement) == checkedElements.size(); 171 } 172 173 177 protected void checkNewTreeElements(Object [] elements) { 178 for (int i = 0; i < elements.length; ++i) { 179 Object currentElement = elements[i]; 180 boolean checked = checkedStateStore.containsKey(currentElement); 181 treeViewer.setChecked(currentElement, checked); 182 treeViewer.setGrayed(currentElement, checked 183 && !whiteCheckedTreeItems.contains(currentElement)); 184 } 185 } 186 187 193 public void checkStateChanged(final CheckStateChangedEvent event) { 194 195 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 197 new Runnable () { 198 public void run() { 199 if (event.getCheckable().equals(treeViewer)) { 200 treeItemChecked(event.getElement(), event 201 .getChecked()); 202 } else { 203 listItemChecked(event.getElement(), event 204 .getChecked(), true); 205 } 206 207 notifyCheckStateChangeListeners(event); 208 } 209 }); 210 } 211 212 219 protected void createContents(Composite parent, int style, 220 boolean useHeightHint) { 221 Composite composite = new Composite(parent, style); 223 composite.setFont(parent.getFont()); 224 GridLayout layout = new GridLayout(); 225 layout.numColumns = 2; 226 layout.makeColumnsEqualWidth = true; 227 layout.marginHeight = 0; 228 layout.marginWidth = 0; 229 composite.setLayout(layout); 230 composite.setLayoutData(new GridData(GridData.FILL_BOTH)); 231 232 createTreeViewer(composite, useHeightHint); 233 createListViewer(composite, useHeightHint); 234 235 initialize(); 236 } 237 238 241 protected void createListViewer(Composite parent, boolean useHeightHint) { 242 listViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER); 243 GridData data = new GridData(GridData.FILL_BOTH); 244 if (useHeightHint) { 245 data.heightHint = PREFERRED_HEIGHT; 246 } 247 listViewer.getTable().setLayoutData(data); 248 listViewer.getTable().setFont(parent.getFont()); 249 listViewer.setContentProvider(listContentProvider); 250 listViewer.setLabelProvider(listLabelProvider); 251 listViewer.addCheckStateListener(this); 252 } 253 254 257 protected void createTreeViewer(Composite parent, boolean useHeightHint) { 258 Tree tree = new Tree(parent, SWT.CHECK | SWT.BORDER); 259 GridData data = new GridData(GridData.FILL_BOTH); 260 if (useHeightHint) { 261 data.heightHint = PREFERRED_HEIGHT; 262 } 263 tree.setLayoutData(data); 264 tree.setFont(parent.getFont()); 265 266 treeViewer = new CheckboxTreeViewer(tree); 267 treeViewer.setContentProvider(treeContentProvider); 268 treeViewer.setLabelProvider(treeLabelProvider); 269 treeViewer.addTreeListener(this); 270 treeViewer.addCheckStateListener(this); 271 treeViewer.addSelectionChangedListener(this); 272 } 273 274 286 protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) { 287 List checked = (List ) checkedStateStore.get(treeElement); 290 if (checked != null && (!checked.isEmpty())) { 291 return true; 292 } 293 294 if (expandedTreeNodes.contains(treeElement)) { 297 Object [] children = treeContentProvider.getChildren(treeElement); 298 for (int i = 0; i < children.length; ++i) { 299 if (checkedStateStore.containsKey(children[i])) { 300 return true; 301 } 302 } 303 } 304 305 return false; 306 } 307 308 315 protected boolean determineShouldBeWhiteChecked(Object treeElement) { 316 return areAllChildrenWhiteChecked(treeElement) 317 && areAllElementsChecked(treeElement); 318 } 319 320 326 protected void determineWhiteCheckedDescendents(Object treeElement) { 327 Object [] children = treeContentProvider.getElements(treeElement); 331 for (int i = 0; i < children.length; ++i) { 332 determineWhiteCheckedDescendents(children[i]); 333 } 334 335 if (determineShouldBeWhiteChecked(treeElement)) { 337 setWhiteChecked(treeElement, true); 338 } 339 } 340 341 344 public void expandAll() { 345 treeViewer.expandAll(); 346 } 347 348 351 private void expandTreeElement(final Object item) { 352 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 353 new Runnable () { 354 public void run() { 355 356 if (expandedTreeNodes.contains(item)) { 359 checkNewTreeElements(treeContentProvider 360 .getChildren(item)); 361 } else { 362 363 expandedTreeNodes.add(item); 364 if (whiteCheckedTreeItems.contains(item)) { 365 Object [] children = treeContentProvider 367 .getChildren(item); 368 for (int i = 0; i < children.length; ++i) { 369 if (!whiteCheckedTreeItems 370 .contains(children[i])) { 371 Object child = children[i]; 372 setWhiteChecked(child, true); 373 treeViewer.setChecked(child, true); 374 checkedStateStore.put(child, 375 new ArrayList ()); 376 } 377 } 378 379 setListForWhiteSelection(item); 381 } 382 } 383 384 } 385 }); 386 } 387 388 396 private void findAllSelectedListElements(Object treeElement, 397 String parentLabel, boolean addAll, IElementFilter filter, 398 IProgressMonitor monitor) throws InterruptedException { 399 400 String fullLabel = null; 401 if (monitor != null && monitor.isCanceled()) { 402 return; 403 } 404 if (monitor != null) { 405 fullLabel = getFullLabel(treeElement, parentLabel); 406 monitor.subTask(fullLabel); 407 } 408 409 if (addAll) { 410 filter.filterElements(listContentProvider.getElements(treeElement), 411 monitor); 412 } else { if (checkedStateStore.containsKey(treeElement)) { 414 filter.filterElements((Collection ) checkedStateStore 415 .get(treeElement), monitor); 416 } 417 } 418 419 Object [] treeChildren = treeContentProvider.getChildren(treeElement); 420 for (int i = 0; i < treeChildren.length; i++) { 421 Object child = treeChildren[i]; 422 if (addAll) { 423 findAllSelectedListElements(child, fullLabel, true, filter, 424 monitor); 425 } else { if (checkedStateStore.containsKey(child)) { 427 findAllSelectedListElements(child, fullLabel, 428 whiteCheckedTreeItems.contains(child), filter, 429 monitor); 430 } 431 } 432 433 } 434 } 435 436 443 private void findAllWhiteCheckedItems(Object treeElement, Collection result) { 444 445 if (whiteCheckedTreeItems.contains(treeElement)) { 446 result.add(treeElement); 447 } else { 448 Collection listChildren = (Collection ) checkedStateStore 449 .get(treeElement); 450 if (listChildren == null) { 452 return; 453 } 454 result.addAll(listChildren); 455 Object [] children = treeContentProvider.getChildren(treeElement); 456 for (int i = 0; i < children.length; ++i) { 457 findAllWhiteCheckedItems(children[i], result); 458 } 459 } 460 } 461 462 474 public void getAllCheckedListItems(IElementFilter filter, 475 IProgressMonitor monitor) throws InterruptedException { 476 477 Object [] children = treeContentProvider.getChildren(root); 479 for (int i = 0; i < children.length; ++i) { 480 findAllSelectedListElements(children[i], null, 481 whiteCheckedTreeItems.contains(children[i]), filter, 482 monitor); 483 } 484 } 485 486 492 public List getAllCheckedListItems() { 493 494 final ArrayList returnValue = new ArrayList (); 495 496 IElementFilter passThroughFilter = new IElementFilter() { 497 498 public void filterElements(Collection elements, 499 IProgressMonitor monitor) { 500 returnValue.addAll(elements); 501 } 502 503 public void filterElements(Object [] elements, 504 IProgressMonitor monitor) { 505 for (int i = 0; i < elements.length; i++) { 506 returnValue.add(elements[i]); 507 } 508 } 509 }; 510 511 try { 512 getAllCheckedListItems(passThroughFilter, null); 513 } catch (InterruptedException exception) { 514 return new ArrayList (); 515 } 516 return returnValue; 517 518 } 519 520 527 public List getAllWhiteCheckedItems() { 528 529 List result = new ArrayList (); 530 531 Object [] children = treeContentProvider.getChildren(root); 533 for (int i = 0; i < children.length; ++i) { 534 findAllWhiteCheckedItems(children[i], result); 535 } 536 537 return result; 538 } 539 540 546 public int getCheckedElementCount() { 547 return checkedStateStore.size(); 548 } 549 550 556 protected String getFullLabel(Object treeElement, String parentLabel) { 557 String label = parentLabel; 558 if (parentLabel == null){ 559 label = ""; } 561 IPath parentName = new Path(label); 562 563 String elementText = treeLabelProvider.getText(treeElement); 564 if(elementText == null) { 565 return parentName.toString(); 566 } 567 return parentName.append(elementText).toString(); 568 } 569 570 577 protected int getListItemsSize(Object treeElement) { 578 Object [] elements = listContentProvider.getElements(treeElement); 579 return elements.length; 580 } 581 582 586 public Table getListTable() { 587 return this.listViewer.getTable(); 588 } 589 590 594 protected void grayCheckHierarchy(Object treeElement) { 595 596 expandTreeElement(treeElement); 598 599 if (checkedStateStore.containsKey(treeElement)) { 601 return; } 603 604 checkedStateStore.put(treeElement, new ArrayList ()); 605 Object parent = treeContentProvider.getParent(treeElement); 606 if (parent != null) { 607 grayCheckHierarchy(parent); 608 } 609 } 610 611 615 private void grayUpdateHierarchy(Object treeElement) { 616 617 boolean shouldBeAtLeastGray = determineShouldBeAtLeastGrayChecked(treeElement); 618 619 treeViewer.setGrayChecked(treeElement, shouldBeAtLeastGray); 620 621 if (whiteCheckedTreeItems.contains(treeElement)) { 622 whiteCheckedTreeItems.remove(treeElement); 623 } 624 625 Object parent = treeContentProvider.getParent(treeElement); 627 if (parent != null) { 628 grayUpdateHierarchy(parent); 629 } 630 } 631 632 636 public void initialCheckListItem(Object element) { 637 Object parent = treeContentProvider.getParent(element); 638 selectAndReveal(parent); 639 listViewer.setChecked(element, true); 641 listItemChecked(element, true, false); 643 grayUpdateHierarchy(parent); 644 } 645 646 651 public void initialCheckTreeItem(Object element) { 652 treeItemChecked(element, true); 653 selectAndReveal(element); 654 } 655 656 private void selectAndReveal(Object treeElement) { 657 treeViewer.reveal(treeElement); 658 IStructuredSelection selection = new StructuredSelection(treeElement); 659 treeViewer.setSelection(selection); 660 } 661 662 665 protected void initialize() { 666 treeViewer.setInput(root); 667 this.expandedTreeNodes = new ArrayList (); 668 this.expandedTreeNodes.add(root); 669 670 } 671 672 677 protected void listItemChecked(Object listElement, boolean state, 678 boolean updatingFromSelection) { 679 List checkedListItems = (List ) checkedStateStore 680 .get(currentTreeSelection); 681 if (!expandedTreeNodes.contains(currentTreeSelection)) { 683 expandTreeElement(currentTreeSelection); 684 } 685 686 if (state) { 687 if (checkedListItems == null) { 688 grayCheckHierarchy(currentTreeSelection); 691 checkedListItems = (List ) checkedStateStore 692 .get(currentTreeSelection); 693 } 694 checkedListItems.add(listElement); 695 } else { 696 checkedListItems.remove(listElement); 697 if (checkedListItems.isEmpty()) { 698 ungrayCheckHierarchy(currentTreeSelection); 701 } 702 } 703 704 if (checkedListItems.size() > 0) { 706 checkedStateStore.put(currentTreeSelection, checkedListItems); 707 } 708 if (updatingFromSelection) { 709 grayUpdateHierarchy(currentTreeSelection); 710 } 711 } 712 713 717 protected void notifyCheckStateChangeListeners( 718 final CheckStateChangedEvent event) { 719 Object [] array = getListeners(); 720 for (int i = 0; i < array.length; i++) { 721 final ICheckStateListener l = (ICheckStateListener) array[i]; 722 SafeRunner.run(new SafeRunnable() { 723 public void run() { 724 l.checkStateChanged(event); 725 } 726 }); 727 } 728 } 729 730 736 protected void populateListViewer(final Object treeElement) { 737 listViewer.setInput(treeElement); 738 739 if (!(expandedTreeNodes.contains(treeElement)) 741 && whiteCheckedTreeItems.contains(treeElement)) { 742 743 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 745 new Runnable () { 746 public void run() { 747 setListForWhiteSelection(treeElement); 748 listViewer.setAllChecked(true); 749 } 750 }); 751 752 } else { 753 List listItemsToCheck = (List ) checkedStateStore.get(treeElement); 754 755 if (listItemsToCheck != null) { 756 Iterator listItemsEnum = listItemsToCheck.iterator(); 757 while (listItemsEnum.hasNext()) { 758 listViewer.setChecked(listItemsEnum.next(), true); 759 } 760 } 761 } 762 } 763 764 769 private void primeHierarchyForSelection(Object item, Set selectedNodes) { 770 771 if (selectedNodes.contains(item)) { 773 return; 774 } 775 776 checkedStateStore.put(item, new ArrayList ()); 777 778 expandedTreeNodes.add(item); 780 selectedNodes.add(item); 781 782 Object parent = treeContentProvider.getParent(item); 783 if (parent != null) { 784 primeHierarchyForSelection(parent, selectedNodes); 785 } 786 } 787 788 794 public void removeCheckStateListener(ICheckStateListener listener) { 795 removeListenerObject(listener); 796 } 797 798 803 public void selectionChanged(SelectionChangedEvent event) { 804 IStructuredSelection selection = (IStructuredSelection) event 805 .getSelection(); 806 Object selectedElement = selection.getFirstElement(); 807 if (selectedElement == null) { 808 currentTreeSelection = null; 809 listViewer.setInput(currentTreeSelection); 810 return; 811 } 812 813 if (selectedElement != currentTreeSelection) { 815 populateListViewer(selectedElement); 816 } 817 818 currentTreeSelection = selectedElement; 819 } 820 821 826 public void setAllSelections(final boolean selection) { 827 828 if (root == null) { 830 return; 831 } 832 833 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 835 new Runnable () { 836 public void run() { 837 setTreeChecked(root, selection); 838 listViewer.setAllChecked(selection); 839 } 840 }); 841 } 842 843 848 private void setListForWhiteSelection(Object treeElement) { 849 850 Object [] listItems = listContentProvider.getElements(treeElement); 851 List listItemsChecked = new ArrayList (); 852 for (int i = 0; i < listItems.length; ++i) { 853 listItemsChecked.add(listItems[i]); 854 } 855 856 checkedStateStore.put(treeElement, listItemsChecked); 857 } 858 859 865 public void setListProviders(IStructuredContentProvider contentProvider, 866 ILabelProvider labelProvider) { 867 listViewer.setContentProvider(contentProvider); 868 listViewer.setLabelProvider(labelProvider); 869 } 870 871 876 public void setListComparator(ViewerComparator comparator) { 877 listViewer.setComparator(comparator); 878 } 879 880 885 public void setRoot(Object newRoot) { 886 this.root = newRoot; 887 initialize(); 888 } 889 890 894 protected void setTreeChecked(Object treeElement, boolean state) { 895 896 if (treeElement.equals(currentTreeSelection)) { 897 listViewer.setAllChecked(state); 898 } 899 900 if (state) { 901 setListForWhiteSelection(treeElement); 902 } else { 903 checkedStateStore.remove(treeElement); 904 } 905 906 setWhiteChecked(treeElement, state); 907 treeViewer.setChecked(treeElement, state); 908 treeViewer.setGrayed(treeElement, false); 909 910 if (expandedTreeNodes.contains(treeElement)) { 912 Object [] children = treeContentProvider.getChildren(treeElement); 913 for (int i = 0; i < children.length; ++i) { 914 setTreeChecked(children[i], state); 915 } 916 } 917 } 918 919 925 public void setTreeProviders(ITreeContentProvider contentProvider, 926 ILabelProvider labelProvider) { 927 treeViewer.setContentProvider(contentProvider); 928 treeViewer.setLabelProvider(labelProvider); 929 } 930 931 936 public void setTreeComparator(ViewerComparator comparator) { 937 treeViewer.setComparator(comparator); 938 } 939 940 946 protected void setWhiteChecked(Object treeElement, boolean isWhiteChecked) { 947 if (isWhiteChecked) { 948 if (!whiteCheckedTreeItems.contains(treeElement)) { 949 whiteCheckedTreeItems.add(treeElement); 950 } 951 } else { 952 whiteCheckedTreeItems.remove(treeElement); 953 } 954 } 955 956 959 public void treeCollapsed(TreeExpansionEvent event) { 960 } 962 963 966 public void treeExpanded(TreeExpansionEvent event) { 967 expandTreeElement(event.getElement()); 968 } 969 970 974 protected void treeItemChecked(Object treeElement, boolean state) { 975 976 setTreeChecked(treeElement, state); 978 979 Object parent = treeContentProvider.getParent(treeElement); 980 if (parent == null) { 981 return; 982 } 983 984 if (state) { 986 grayCheckHierarchy(parent); 987 } else { 988 ungrayCheckHierarchy(parent); 989 } 990 991 grayUpdateHierarchy(parent); 993 } 994 995 998 protected void ungrayCheckHierarchy(Object treeElement) { 999 if (!determineShouldBeAtLeastGrayChecked(treeElement)) { 1000 checkedStateStore.remove(treeElement); 1001 } 1002 1003 Object parent = treeContentProvider.getParent(treeElement); 1004 if (parent != null) { 1005 ungrayCheckHierarchy(parent); 1006 } 1007 } 1008 1009 1012 protected void updateHierarchy(Object treeElement) { 1013 1014 boolean whiteChecked = determineShouldBeWhiteChecked(treeElement); 1015 boolean shouldBeAtLeastGray = determineShouldBeAtLeastGrayChecked(treeElement); 1016 1017 treeViewer.setChecked(treeElement, shouldBeAtLeastGray); 1018 setWhiteChecked(treeElement, whiteChecked); 1019 if (whiteChecked) { 1020 treeViewer.setGrayed(treeElement, false); 1021 } else { 1022 treeViewer.setGrayed(treeElement, shouldBeAtLeastGray); 1023 } 1024 1025 Object parent = treeContentProvider.getParent(treeElement); 1027 if (parent != null) { 1028 grayUpdateHierarchy(parent); 1029 } 1030 } 1031 1032 1041 public void updateSelections(Map items) { 1042 this.listViewer.setAllChecked(false); 1045 this.treeViewer.setCheckedElements(new Object [0]); 1046 this.whiteCheckedTreeItems = new HashSet (); 1047 Set selectedNodes = new HashSet (); 1048 checkedStateStore = new HashMap (); 1049 1050 Iterator keyIterator = items.keySet().iterator(); 1052 while (keyIterator.hasNext()) { 1053 Object key = keyIterator.next(); 1054 List selections = (List ) items.get(key); 1055 checkedStateStore.put(key, selections); 1057 selectedNodes.add(key); 1058 Object parent = treeContentProvider.getParent(key); 1060 if (parent != null) { 1061 primeHierarchyForSelection(parent, selectedNodes); 1063 } 1064 } 1065 1066 treeViewer.setCheckedElements(checkedStateStore.keySet().toArray()); 1069 treeViewer.setGrayedElements(checkedStateStore.keySet().toArray()); 1070 1071 if (currentTreeSelection != null) { 1073 Object displayItems = items.get(currentTreeSelection); 1074 if (displayItems != null) { 1075 listViewer.setCheckedElements(((List ) displayItems).toArray()); 1076 } 1077 } 1078 } 1079 1080 1083 public void setFocus() { 1084 1085 this.treeViewer.getTree().setFocus(); 1086 } 1087 1088} 1089 1090 | Popular Tags |