1 11 package org.eclipse.ui.internal.ide.misc; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 import java.util.Set ; 19 20 import org.eclipse.core.commands.common.EventManager; 21 import org.eclipse.core.runtime.SafeRunner; 22 import org.eclipse.jface.util.SafeRunnable; 23 import org.eclipse.jface.viewers.CheckStateChangedEvent; 24 import org.eclipse.jface.viewers.CheckboxTableViewer; 25 import org.eclipse.jface.viewers.CheckboxTreeViewer; 26 import org.eclipse.jface.viewers.ICheckStateListener; 27 import org.eclipse.jface.viewers.ILabelProvider; 28 import org.eclipse.jface.viewers.ISelectionChangedListener; 29 import org.eclipse.jface.viewers.IStructuredContentProvider; 30 import org.eclipse.jface.viewers.IStructuredSelection; 31 import org.eclipse.jface.viewers.ITreeContentProvider; 32 import org.eclipse.jface.viewers.ITreeViewerListener; 33 import org.eclipse.jface.viewers.SelectionChangedEvent; 34 import org.eclipse.jface.viewers.StructuredSelection; 35 import org.eclipse.jface.viewers.TreeExpansionEvent; 36 import org.eclipse.jface.viewers.ViewerComparator; 37 import org.eclipse.swt.SWT; 38 import org.eclipse.swt.custom.BusyIndicator; 39 import org.eclipse.swt.layout.GridData; 40 import org.eclipse.swt.layout.GridLayout; 41 import org.eclipse.swt.widgets.Composite; 42 import org.eclipse.swt.widgets.Table; 43 import org.eclipse.swt.widgets.Tree; 44 45 49 public class CheckboxTreeAndListGroup extends EventManager implements 50 ICheckStateListener, ISelectionChangedListener, ITreeViewerListener { 51 private Object root; 52 53 private Object currentTreeSelection; 54 55 private List expandedTreeNodes = new ArrayList (); 56 57 private Map checkedStateStore = new HashMap (9); 58 59 private List whiteCheckedTreeItems = new ArrayList (); 60 61 private ITreeContentProvider treeContentProvider; 62 63 private IStructuredContentProvider listContentProvider; 64 65 private ILabelProvider treeLabelProvider; 66 67 private ILabelProvider listLabelProvider; 68 69 private CheckboxTreeViewer treeViewer; 71 72 private CheckboxTableViewer listViewer; 73 74 88 public CheckboxTreeAndListGroup(Composite parent, Object rootObject, 89 ITreeContentProvider treeContentProvider, 90 ILabelProvider treeLabelProvider, 91 IStructuredContentProvider listContentProvider, 92 ILabelProvider listLabelProvider, int style, int width, int height) { 93 94 root = rootObject; 95 this.treeContentProvider = treeContentProvider; 96 this.listContentProvider = listContentProvider; 97 this.treeLabelProvider = treeLabelProvider; 98 this.listLabelProvider = listLabelProvider; 99 createContents(parent, width, height, style); 100 } 101 102 105 public void aboutToOpen() { 106 determineWhiteCheckedDescendents(root); 107 checkNewTreeElements(treeContentProvider.getElements(root)); 108 currentTreeSelection = null; 109 110 Object [] elements = treeContentProvider.getElements(root); 112 Object primary = elements.length > 0 ? elements[0] : null; 113 if (primary != null) { 114 treeViewer.setSelection(new StructuredSelection(primary)); 115 } 116 treeViewer.getControl().setFocus(); 117 } 118 119 125 public void addCheckStateListener(ICheckStateListener listener) { 126 addListenerObject(listener); 127 } 128 129 133 private void addToHierarchyToCheckedStore(Object treeElement) { 134 135 if (!checkedStateStore.containsKey(treeElement)) { 137 checkedStateStore.put(treeElement, new ArrayList ()); 138 } 139 140 Object parent = treeContentProvider.getParent(treeElement); 141 if (parent != null) { 142 addToHierarchyToCheckedStore(parent); 143 } 144 } 145 146 153 protected boolean areAllChildrenWhiteChecked(Object treeElement) { 154 Object [] children = treeContentProvider.getChildren(treeElement); 155 for (int i = 0; i < children.length; ++i) { 156 if (!whiteCheckedTreeItems.contains(children[i])) { 157 return false; 158 } 159 } 160 161 return true; 162 } 163 164 171 protected boolean areAllElementsChecked(Object treeElement) { 172 List checkedElements = (List ) checkedStateStore.get(treeElement); 173 if (checkedElements == null) { 174 return false; 175 } 176 177 return getListItemsSize(treeElement) == checkedElements.size(); 178 } 179 180 184 protected void checkNewTreeElements(Object [] elements) { 185 for (int i = 0; i < elements.length; ++i) { 186 Object currentElement = elements[i]; 187 boolean checked = checkedStateStore.containsKey(currentElement); 188 treeViewer.setChecked(currentElement, checked); 189 treeViewer.setGrayed(currentElement, checked 190 && !whiteCheckedTreeItems.contains(currentElement)); 191 } 192 } 193 194 200 public void checkStateChanged(final CheckStateChangedEvent event) { 201 202 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 204 new Runnable () { 205 public void run() { 206 if (event.getCheckable().equals(treeViewer)) { 207 treeItemChecked(event.getElement(), event 208 .getChecked()); 209 } else { 210 listItemChecked(event.getElement(), event 211 .getChecked(), true); 212 } 213 214 notifyCheckStateChangeListeners(event); 215 } 216 }); 217 } 218 219 226 protected void createContents(Composite parent, int width, int height, 227 int style) { 228 Composite composite = new Composite(parent, style); 230 GridLayout layout = new GridLayout(); 231 layout.numColumns = 2; 232 layout.makeColumnsEqualWidth = true; 233 layout.marginHeight = 0; 234 layout.marginWidth = 0; 235 composite.setLayout(layout); 236 composite.setLayoutData(new GridData(GridData.FILL_BOTH)); 237 composite.setFont(parent.getFont()); 238 239 createTreeViewer(composite, width / 2, height); 240 createListViewer(composite, width / 2, height); 241 242 initialize(); 243 } 244 245 248 protected void createListViewer(Composite parent, int width, int height) { 249 listViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER); 250 GridData data = new GridData(GridData.FILL_BOTH); 251 data.widthHint = width; 252 data.heightHint = height; 253 listViewer.getTable().setLayoutData(data); 254 listViewer.getTable().setFont(parent.getFont()); 255 listViewer.setContentProvider(listContentProvider); 256 listViewer.setLabelProvider(listLabelProvider); 257 listViewer.addCheckStateListener(this); 258 } 259 260 263 protected void createTreeViewer(Composite parent, int width, int height) { 264 Tree tree = new Tree(parent, SWT.CHECK | SWT.BORDER); 265 GridData data = new GridData(GridData.FILL_BOTH); 266 data.widthHint = width; 267 data.heightHint = height; 268 tree.setLayoutData(data); 269 tree.setFont(parent.getFont()); 270 271 treeViewer = new CheckboxTreeViewer(tree); 272 treeViewer.setContentProvider(treeContentProvider); 273 treeViewer.setLabelProvider(treeLabelProvider); 274 treeViewer.addTreeListener(this); 275 treeViewer.addCheckStateListener(this); 276 treeViewer.addSelectionChangedListener(this); 277 } 278 279 291 protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) { 292 List checked = (List ) checkedStateStore.get(treeElement); 295 if (checked != null && (!checked.isEmpty())) { 296 return true; 297 } 298 299 Object [] children = treeContentProvider.getChildren(treeElement); 302 for (int i = 0; i < children.length; ++i) { 303 if (checkedStateStore.containsKey(children[i])) { 304 return true; 305 } 306 } 307 308 return false; 309 } 310 311 318 protected boolean determineShouldBeWhiteChecked(Object treeElement) { 319 return areAllChildrenWhiteChecked(treeElement) 320 && areAllElementsChecked(treeElement); 321 } 322 323 329 protected void determineWhiteCheckedDescendents(Object treeElement) { 330 Object [] children = treeContentProvider.getElements(treeElement); 334 for (int i = 0; i < children.length; ++i) { 335 determineWhiteCheckedDescendents(children[i]); 336 } 337 338 if (determineShouldBeWhiteChecked(treeElement)) { 340 setWhiteChecked(treeElement, true); 341 } 342 } 343 344 347 public void expandAll() { 348 treeViewer.expandAll(); 349 } 350 351 357 public Iterator getAllCheckedListItems() { 358 List result = new ArrayList (); 359 Iterator listCollectionsEnum = checkedStateStore.values().iterator(); 360 361 while (listCollectionsEnum.hasNext()) { 362 Iterator currentCollection = ((List ) listCollectionsEnum.next()) 363 .iterator(); 364 while (currentCollection.hasNext()) { 365 result.add(currentCollection.next()); 366 } 367 } 368 369 return result.iterator(); 370 } 371 372 378 public Set getAllCheckedTreeItems() { 379 return checkedStateStore.keySet(); 380 } 381 382 388 public int getCheckedElementCount() { 389 return checkedStateStore.size(); 390 } 391 392 399 protected int getListItemsSize(Object treeElement) { 400 Object [] elements = listContentProvider.getElements(treeElement); 401 return elements.length; 402 } 403 404 408 public Table getListTable() { 409 return this.listViewer.getTable(); 410 } 411 412 416 protected void grayCheckHierarchy(Object treeElement) { 417 418 if (checkedStateStore.containsKey(treeElement)) { 420 return; } 422 423 checkedStateStore.put(treeElement, new ArrayList ()); 424 if (determineShouldBeWhiteChecked(treeElement)) { 425 setWhiteChecked(treeElement, true); 426 } 427 Object parent = treeContentProvider.getParent(treeElement); 428 if (parent != null) { 429 grayCheckHierarchy(parent); 430 } 431 } 432 433 438 public void initialCheckListItem(Object element) { 439 Object parent = treeContentProvider.getParent(element); 440 currentTreeSelection = parent; 441 listItemChecked(element, true, false); 443 updateHierarchy(parent); 444 } 445 446 452 public void initialCheckTreeItem(Object element) { 453 treeItemChecked(element, true); 454 } 455 456 459 protected void initialize() { 460 treeViewer.setInput(root); 461 } 462 463 468 protected void listItemChecked(Object listElement, boolean state, 469 boolean updatingFromSelection) { 470 List checkedListItems = (List ) checkedStateStore 471 .get(currentTreeSelection); 472 473 if (state) { 474 if (checkedListItems == null) { 475 grayCheckHierarchy(currentTreeSelection); 478 checkedListItems = (List ) checkedStateStore 479 .get(currentTreeSelection); 480 } 481 checkedListItems.add(listElement); 482 } else { 483 checkedListItems.remove(listElement); 484 if (checkedListItems.isEmpty()) { 485 ungrayCheckHierarchy(currentTreeSelection); 488 } 489 } 490 491 if (updatingFromSelection) { 492 updateHierarchy(currentTreeSelection); 493 } 494 } 495 496 500 protected void notifyCheckStateChangeListeners( 501 final CheckStateChangedEvent event) { 502 Object [] array = getListeners(); 503 for (int i = 0; i < array.length; i++) { 504 final ICheckStateListener l = (ICheckStateListener) array[i]; 505 SafeRunner.run(new SafeRunnable() { 506 public void run() { 507 l.checkStateChanged(event); 508 } 509 }); 510 } 511 } 512 513 519 protected void populateListViewer(final Object treeElement) { 520 listViewer.setInput(treeElement); 521 List listItemsToCheck = (List ) checkedStateStore.get(treeElement); 522 523 if (listItemsToCheck != null) { 524 Iterator listItemsEnum = listItemsToCheck.iterator(); 525 while (listItemsEnum.hasNext()) { 526 listViewer.setChecked(listItemsEnum.next(), true); 527 } 528 } 529 } 530 531 537 public void removeCheckStateListener(ICheckStateListener listener) { 538 removeListenerObject(listener); 539 } 540 541 546 public void selectionChanged(SelectionChangedEvent event) { 547 IStructuredSelection selection = (IStructuredSelection) event 548 .getSelection(); 549 Object selectedElement = selection.getFirstElement(); 550 if (selectedElement == null) { 551 currentTreeSelection = null; 552 listViewer.setInput(currentTreeSelection); 553 return; 554 } 555 556 if (selectedElement != currentTreeSelection) { 558 populateListViewer(selectedElement); 559 } 560 561 currentTreeSelection = selectedElement; 562 } 563 564 570 public void setAllSelections(final boolean selection) { 571 572 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 574 new Runnable () { 575 public void run() { 576 setTreeChecked(root, selection); 577 listViewer.setAllChecked(selection); 578 } 579 }); 580 } 581 582 588 public void setListProviders(IStructuredContentProvider contentProvider, 589 ILabelProvider labelProvider) { 590 listViewer.setContentProvider(contentProvider); 591 listViewer.setLabelProvider(labelProvider); 592 } 593 594 599 public void setListComparator(ViewerComparator comparator) { 600 listViewer.setComparator(comparator); 601 } 602 603 608 public void setRoot(Object newRoot) { 609 this.root = newRoot; 610 initialize(); 611 } 612 613 617 protected void setTreeChecked(Object treeElement, boolean state) { 618 619 if (treeElement.equals(currentTreeSelection)) { 620 listViewer.setAllChecked(state); 621 } 622 623 if (state) { 624 Object [] listItems = listContentProvider.getElements(treeElement); 625 List listItemsChecked = new ArrayList (); 626 for (int i = 0; i < listItems.length; ++i) { 627 listItemsChecked.add(listItems[i]); 628 } 629 630 checkedStateStore.put(treeElement, listItemsChecked); 631 } else { 632 checkedStateStore.remove(treeElement); 633 } 634 635 setWhiteChecked(treeElement, state); 636 treeViewer.setChecked(treeElement, state); 637 treeViewer.setGrayed(treeElement, false); 638 639 Object [] children = treeContentProvider.getChildren(treeElement); 641 for (int i = 0; i < children.length; ++i) { 642 setTreeChecked(children[i], state); 643 } 644 } 645 646 652 public void setTreeProviders(ITreeContentProvider contentProvider, 653 ILabelProvider labelProvider) { 654 treeViewer.setContentProvider(contentProvider); 655 treeViewer.setLabelProvider(labelProvider); 656 } 657 658 663 public void setTreeComparator(ViewerComparator comparator) { 664 treeViewer.setComparator(comparator); 665 } 666 667 673 protected void setWhiteChecked(Object treeElement, boolean isWhiteChecked) { 674 if (isWhiteChecked) { 675 if (!whiteCheckedTreeItems.contains(treeElement)) { 676 whiteCheckedTreeItems.add(treeElement); 677 } 678 } else { 679 whiteCheckedTreeItems.remove(treeElement); 680 } 681 } 682 683 686 public void treeCollapsed(TreeExpansionEvent event) { 687 } 689 690 693 public void treeExpanded(TreeExpansionEvent event) { 694 695 Object item = event.getElement(); 696 697 if (!expandedTreeNodes.contains(item)) { 700 expandedTreeNodes.add(item); 701 checkNewTreeElements(treeContentProvider.getChildren(item)); 702 } 703 } 704 705 709 protected void treeItemChecked(Object treeElement, boolean state) { 710 711 setTreeChecked(treeElement, state); 713 714 Object parent = treeContentProvider.getParent(treeElement); 715 if (parent == null) { 716 return; 717 } 718 719 if (state) { 721 grayCheckHierarchy(parent); 722 } else { 723 ungrayCheckHierarchy(parent); 724 } 725 726 updateHierarchy(treeElement); 727 } 728 729 732 protected void ungrayCheckHierarchy(Object treeElement) { 733 if (!determineShouldBeAtLeastGrayChecked(treeElement)) { 734 checkedStateStore.remove(treeElement); 735 } 736 737 Object parent = treeContentProvider.getParent(treeElement); 738 if (parent != null) { 739 ungrayCheckHierarchy(parent); 740 } 741 } 742 743 746 protected void updateHierarchy(Object treeElement) { 747 748 boolean whiteChecked = determineShouldBeWhiteChecked(treeElement); 749 boolean shouldBeAtLeastGray = determineShouldBeAtLeastGrayChecked(treeElement); 750 751 treeViewer.setChecked(treeElement, shouldBeAtLeastGray); 752 setWhiteChecked(treeElement, whiteChecked); 753 if (!whiteChecked) { 754 treeViewer.setGrayed(treeElement, shouldBeAtLeastGray); 755 } 756 757 Object parent = treeContentProvider.getParent(treeElement); 759 if (parent != null) { 760 updateHierarchy(parent); 761 } 762 } 763 764 770 public void updateSelections(final Map items) { 771 772 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), 774 new Runnable () { 775 public void run() { 776 Iterator keyIterator = items.keySet().iterator(); 777 778 while (keyIterator.hasNext()) { 780 Object key = keyIterator.next(); 781 List selections = (List ) items.get(key); 783 if (selections.size() == 0) { 784 checkedStateStore.remove(key); 786 } else { 787 checkedStateStore.put(key, selections); 788 Object parent = treeContentProvider 790 .getParent(key); 791 if (parent != null) { 792 addToHierarchyToCheckedStore(parent); 793 } 794 } 795 } 796 797 keyIterator = items.keySet().iterator(); 799 800 while (keyIterator.hasNext()) { 801 Object key = keyIterator.next(); 802 updateHierarchy(key); 803 if (currentTreeSelection != null 804 && currentTreeSelection.equals(key)) { 805 listViewer.setAllChecked(false); 806 listViewer.setCheckedElements(((List ) items 807 .get(key)).toArray()); 808 } 809 } 810 } 811 }); 812 813 } 814 } 815 | Popular Tags |