1 11 package org.eclipse.jdt.internal.ui.jarpackager; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 import java.util.Set ; 20 21 import org.eclipse.swt.SWT; 22 import org.eclipse.swt.custom.BusyIndicator; 23 import org.eclipse.swt.layout.GridData; 24 import org.eclipse.swt.layout.GridLayout; 25 import org.eclipse.swt.widgets.Composite; 26 import org.eclipse.swt.widgets.Table; 27 import org.eclipse.swt.widgets.Tree; 28 29 import org.eclipse.jface.viewers.CheckStateChangedEvent; 30 import org.eclipse.jface.viewers.CheckboxTableViewer; 31 import org.eclipse.jface.viewers.CheckboxTreeViewer; 32 import org.eclipse.jface.viewers.ICheckStateListener; 33 import org.eclipse.jface.viewers.ILabelProvider; 34 import org.eclipse.jface.viewers.ISelection; 35 import org.eclipse.jface.viewers.ISelectionChangedListener; 36 import org.eclipse.jface.viewers.IStructuredContentProvider; 37 import org.eclipse.jface.viewers.IStructuredSelection; 38 import org.eclipse.jface.viewers.ITreeContentProvider; 39 import org.eclipse.jface.viewers.ITreeViewerListener; 40 import org.eclipse.jface.viewers.SelectionChangedEvent; 41 import org.eclipse.jface.viewers.StructuredSelection; 42 import org.eclipse.jface.viewers.TreeExpansionEvent; 43 import org.eclipse.jface.viewers.ViewerComparator; 44 import org.eclipse.jface.viewers.ViewerFilter; 45 46 50 public class CheckboxTreeAndListGroup implements ICheckStateListener, ISelectionChangedListener, ITreeViewerListener { 51 52 private Object fRoot; 53 private Object fCurrentTreeSelection; 54 private List fExpandedTreeNodes= new ArrayList (); 55 private Map fCheckedStateStore= new HashMap (9); 56 private List fWhiteCheckedTreeItems= new ArrayList (); 57 private List fListeners= new ArrayList (); 58 59 private ITreeContentProvider fTreeContentProvider; 60 private IStructuredContentProvider fListContentProvider; 61 private ILabelProvider fTreeLabelProvider; 62 private ILabelProvider fListLabelProvider; 63 64 private CheckboxTreeViewer fTreeViewer; 66 private CheckboxTableViewer fListViewer; 67 68 73 public CheckboxTreeAndListGroup( 74 Composite parent, 75 Object rootObject, 76 ITreeContentProvider treeContentProvider, 77 ILabelProvider treeLabelProvider, 78 IStructuredContentProvider listContentProvider, 79 ILabelProvider listLabelProvider, 80 int style, 81 int width, 82 int height) { 83 fRoot= rootObject; 84 fTreeContentProvider= treeContentProvider; 85 fListContentProvider= listContentProvider; 86 fTreeLabelProvider= treeLabelProvider; 87 fListLabelProvider= listLabelProvider; 88 createContents(parent, width, height, style); 89 } 90 93 public void aboutToOpen() { 94 determineWhiteCheckedDescendents(fRoot); 95 checkNewTreeElements(getTreeChildren(fRoot)); 96 fCurrentTreeSelection= null; 97 98 Object [] elements= getTreeChildren(fRoot); 100 Object primary= elements.length > 0 ? elements[0] : null; 101 if (primary != null) { 102 fTreeViewer.setSelection(new StructuredSelection(primary)); 103 } 104 fTreeViewer.getControl().setFocus(); 105 } 106 112 public void addCheckStateListener(ICheckStateListener listener) { 113 fListeners.add(listener); 114 } 115 119 private void addToHierarchyToCheckedStore(Object treeElement) { 120 121 if (!fCheckedStateStore.containsKey(treeElement)) 123 fCheckedStateStore.put(treeElement, new ArrayList ()); 124 125 Object parent= fTreeContentProvider.getParent(treeElement); 126 if (parent != null) 127 addToHierarchyToCheckedStore(parent); 128 } 129 136 protected boolean areAllChildrenWhiteChecked(Object treeElement) { 137 Object [] children= getTreeChildren(treeElement); 138 for (int i= 0; i < children.length; ++i) { 139 if (!fWhiteCheckedTreeItems.contains(children[i])) 140 return false; 141 } 142 143 return true; 144 } 145 152 protected boolean areAllElementsChecked(Object treeElement) { 153 List checkedElements= (List )fCheckedStateStore.get(treeElement); 154 if (checkedElements == null) return false; 156 157 return getListItemsSize(treeElement) == checkedElements.size(); 158 } 159 163 protected void checkNewTreeElements(Object [] elements) { 164 for (int i= 0; i < elements.length; ++i) { 165 Object currentElement= elements[i]; 166 boolean checked= fCheckedStateStore.containsKey(currentElement); 167 fTreeViewer.setChecked(currentElement, checked); 168 fTreeViewer.setGrayed( 169 currentElement, 170 checked && !fWhiteCheckedTreeItems.contains(currentElement)); 171 } 172 } 173 179 public void checkStateChanged(final CheckStateChangedEvent event) { 180 181 BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable () { 183 public void run() { 184 if (event.getCheckable().equals(fTreeViewer)) 185 treeItemChecked(event.getElement(), event.getChecked()); 186 else 187 listItemChecked(event.getElement(), event.getChecked(), true); 188 189 notifyCheckStateChangeListeners(event); 190 } 191 }); 192 } 193 200 protected void createContents( 201 Composite parent, 202 int width, 203 int height, 204 int style) { 205 Composite composite= new Composite(parent, style); 207 GridLayout layout= new GridLayout(); 208 layout.numColumns= 2; 209 layout.makeColumnsEqualWidth= true; 210 layout.marginHeight= 0; 211 layout.marginWidth= 0; 212 composite.setLayout(layout); 213 composite.setLayoutData(new GridData(GridData.FILL_BOTH)); 214 215 createTreeViewer(composite, width / 2, height); 216 createListViewer(composite, width / 2, height); 217 218 initialize(); 219 } 220 223 protected void createListViewer(Composite parent, int width, int height) { 224 fListViewer= CheckboxTableViewer.newCheckList(parent, SWT.BORDER); 225 fListViewer.setUseHashlookup(true); 226 GridData data= new GridData(GridData.FILL_BOTH); 227 data.widthHint= width; 228 data.heightHint= height; 229 fListViewer.getTable().setLayoutData(data); 230 fListViewer.setContentProvider(fListContentProvider); 231 fListViewer.setLabelProvider(fListLabelProvider); 232 fListViewer.addCheckStateListener(this); 233 } 234 237 protected void createTreeViewer(Composite parent, int width, int height) { 238 Tree tree= new Tree(parent, SWT.CHECK | SWT.BORDER); 239 GridData data= new GridData(GridData.FILL_BOTH); 240 data.widthHint= width; 241 data.heightHint= height; 242 tree.setLayoutData(data); 243 244 fTreeViewer= new CheckboxTreeViewer(tree); 245 fTreeViewer.setUseHashlookup(true); 246 fTreeViewer.setContentProvider(fTreeContentProvider); 247 fTreeViewer.setLabelProvider(fTreeLabelProvider); 248 fTreeViewer.addTreeListener(this); 249 fTreeViewer.addCheckStateListener(this); 250 fTreeViewer.addSelectionChangedListener(this); 251 } 252 264 protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) { 265 List checked= (List ) fCheckedStateStore.get(treeElement); 268 if (checked != null && (!checked.isEmpty())) 269 return true; 270 271 Object [] children= getTreeChildren(treeElement); 274 for (int i= 0; i < children.length; ++i) { 275 if (fCheckedStateStore.containsKey(children[i])) 276 return true; 277 } 278 279 return false; 280 } 281 288 protected boolean determineShouldBeWhiteChecked(Object treeElement) { 289 return areAllChildrenWhiteChecked(treeElement) 290 && areAllElementsChecked(treeElement); 291 } 292 298 protected void determineWhiteCheckedDescendents(Object treeElement) { 299 Object [] children= getTreeChildren(treeElement); 303 for (int i= 0; i < children.length; ++i) 304 determineWhiteCheckedDescendents(children[i]); 305 306 if (determineShouldBeWhiteChecked(treeElement)) 308 setWhiteChecked(treeElement, true); 309 } 310 313 public void expandAll() { 314 fTreeViewer.expandAll(); 315 } 316 322 public Iterator getAllCheckedListItems() { 323 Set result= new HashSet (); 324 Iterator listCollectionsEnum= fCheckedStateStore.values().iterator(); 325 while (listCollectionsEnum.hasNext()) 326 result.addAll((List )listCollectionsEnum.next()); 327 return result.iterator(); 328 } 329 335 public Set getAllCheckedTreeItems() { 336 return new HashSet (fCheckedStateStore.keySet()); 337 } 338 344 public int getCheckedElementCount() { 345 return fCheckedStateStore.size(); 346 } 347 354 protected int getListItemsSize(Object treeElement) { 355 Object [] elements= getListElements(treeElement); 356 return elements.length; 357 } 358 363 public Table getTable() { 364 return fListViewer.getTable(); 365 } 366 371 public Tree getTree() { 372 return fTreeViewer.getTree(); 373 } 374 380 public void addTreeFilter(ViewerFilter filter) { 381 fTreeViewer.addFilter(filter); 382 } 383 389 public void addListFilter(ViewerFilter filter) { 390 fListViewer.addFilter(filter); 391 } 392 396 protected void grayCheckHierarchy(Object treeElement) { 397 398 if (fCheckedStateStore.containsKey(treeElement)) 400 return; 402 fCheckedStateStore.put(treeElement, new ArrayList ()); 403 if (determineShouldBeWhiteChecked(treeElement)) { 404 setWhiteChecked(treeElement, true); 405 } 406 Object parent= fTreeContentProvider.getParent(treeElement); 407 if (parent != null) 408 grayCheckHierarchy(parent); 409 } 410 413 public void initialCheckListItem(Object element) { 414 Object parent= fTreeContentProvider.getParent(element); 415 fCurrentTreeSelection= parent; 416 listItemChecked(element, true, false); 418 updateHierarchy(parent); 419 } 420 424 public void initialCheckTreeItem(Object element) { 425 treeItemChecked(element, true); 426 } 427 430 protected void initialize() { 431 fTreeViewer.setInput(fRoot); 432 } 433 438 protected void listItemChecked( 439 Object listElement, 440 boolean state, 441 boolean updatingFromSelection) { 442 List checkedListItems= (List ) fCheckedStateStore.get(fCurrentTreeSelection); 443 444 if (state) { 445 if (checkedListItems == null) { 446 grayCheckHierarchy(fCurrentTreeSelection); 449 checkedListItems= (List ) fCheckedStateStore.get(fCurrentTreeSelection); 450 } 451 checkedListItems.add(listElement); 452 } else { 453 checkedListItems.remove(listElement); 454 if (checkedListItems.isEmpty()) { 455 ungrayCheckHierarchy(fCurrentTreeSelection); 458 } 459 } 460 461 if (updatingFromSelection) 462 updateHierarchy(fCurrentTreeSelection); 463 } 464 468 protected void notifyCheckStateChangeListeners(CheckStateChangedEvent event) { 469 Iterator listenersEnum= fListeners.iterator(); 470 while (listenersEnum.hasNext()) 471 ((ICheckStateListener) listenersEnum.next()).checkStateChanged(event); 472 } 473 479 protected void populateListViewer(final Object treeElement) { 480 if (treeElement == fCurrentTreeSelection) 481 return; 482 fCurrentTreeSelection= treeElement; 483 fListViewer.setInput(treeElement); 484 List listItemsToCheck= (List ) fCheckedStateStore.get(treeElement); 485 486 if (listItemsToCheck != null) { 487 Iterator listItemsEnum= listItemsToCheck.iterator(); 488 while (listItemsEnum.hasNext()) 489 fListViewer.setChecked(listItemsEnum.next(), true); 490 } 491 } 492 498 public void removeCheckStateListener(ICheckStateListener listener) { 499 fListeners.remove(listener); 500 } 501 506 public void selectionChanged(final SelectionChangedEvent event) { 507 BusyIndicator.showWhile(getTable().getShell().getDisplay(), new Runnable () { 508 public void run() { 509 IStructuredSelection selection= (IStructuredSelection) event.getSelection(); 510 Object selectedElement= selection.getFirstElement(); 511 if (selectedElement == null) { 512 fCurrentTreeSelection= null; 513 fListViewer.setInput(fCurrentTreeSelection); 514 return; 515 } 516 populateListViewer(selectedElement); 517 } 518 }); 519 } 520 521 525 public void setAllSelections(final boolean selection) { 526 527 BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable () { 529 public void run() { 530 setTreeChecked(fRoot, selection); 531 fListViewer.setAllChecked(selection); 532 } 533 }); 534 } 535 536 542 public void setListProviders( 543 IStructuredContentProvider contentProvider, 544 ILabelProvider labelProvider) { 545 fListViewer.setContentProvider(contentProvider); 546 fListViewer.setLabelProvider(labelProvider); 547 } 548 551 public void setListComparator(ViewerComparator comparator) { 552 fListViewer.setComparator(comparator); 553 } 554 560 public void setRoot(Object newRoot) { 561 this.fRoot= newRoot; 562 initialize(); 563 } 564 568 protected void setTreeChecked(Object treeElement, boolean state) { 569 570 if (treeElement.equals(fCurrentTreeSelection)) { 571 fListViewer.setAllChecked(state); 572 } 573 574 if (state) { 575 Object [] listItems= getListElements(treeElement); 576 List listItemsChecked= new ArrayList (); 577 for (int i= 0; i < listItems.length; ++i) 578 listItemsChecked.add(listItems[i]); 579 580 fCheckedStateStore.put(treeElement, listItemsChecked); 581 } else 582 fCheckedStateStore.remove(treeElement); 583 584 setWhiteChecked(treeElement, state); 585 fTreeViewer.setChecked(treeElement, state); 586 fTreeViewer.setGrayed(treeElement, false); 587 588 Object [] children= getTreeChildren(treeElement); 590 for (int i= 0; i < children.length; ++i) { 591 setTreeChecked(children[i], state); 592 } 593 } 594 600 public void setTreeProviders( 601 ITreeContentProvider contentProvider, 602 ILabelProvider labelProvider) { 603 fTreeViewer.setContentProvider(contentProvider); 604 fTreeViewer.setLabelProvider(labelProvider); 605 } 606 609 public void setTreeComparator(ViewerComparator sorter) { 610 fTreeViewer.setComparator(sorter); 611 } 612 618 protected void setWhiteChecked(Object treeElement, boolean isWhiteChecked) { 619 if (isWhiteChecked) { 620 if (!fWhiteCheckedTreeItems.contains(treeElement)) 621 fWhiteCheckedTreeItems.add(treeElement); 622 } else 623 fWhiteCheckedTreeItems.remove(treeElement); 624 } 625 628 public void treeCollapsed(TreeExpansionEvent event) { 629 } 631 632 635 public void treeExpanded(TreeExpansionEvent event) { 636 637 Object item= event.getElement(); 638 639 if (!fExpandedTreeNodes.contains(item)) { 642 fExpandedTreeNodes.add(item); 643 checkNewTreeElements(getTreeChildren(item)); 644 } 645 } 646 647 651 protected void treeItemChecked(Object treeElement, boolean state) { 652 653 setTreeChecked(treeElement, state); 655 656 Object parent= fTreeContentProvider.getParent(treeElement); 657 if (parent == null) 658 return; 659 660 if (state) 662 grayCheckHierarchy(parent); 663 else 664 ungrayCheckHierarchy(parent); 665 666 updateHierarchy(treeElement); 667 } 668 671 protected void ungrayCheckHierarchy(Object treeElement) { 672 if (!determineShouldBeAtLeastGrayChecked(treeElement)) 673 fCheckedStateStore.remove(treeElement); 674 675 Object parent= fTreeContentProvider.getParent(treeElement); 676 if (parent != null) 677 ungrayCheckHierarchy(parent); 678 } 679 682 protected void updateHierarchy(Object treeElement) { 683 684 boolean whiteChecked= determineShouldBeWhiteChecked(treeElement); 685 boolean shouldBeAtLeastGray= determineShouldBeAtLeastGrayChecked(treeElement); 686 687 fTreeViewer.setChecked(treeElement, whiteChecked || shouldBeAtLeastGray); 688 setWhiteChecked(treeElement, whiteChecked); 689 if (whiteChecked) 690 fTreeViewer.setGrayed(treeElement, false); 691 else 692 fTreeViewer.setGrayed(treeElement, shouldBeAtLeastGray); 693 694 Object parent= fTreeContentProvider.getParent(treeElement); 696 if (parent != null) { 697 updateHierarchy(parent); 698 } 699 } 700 707 public void updateSelections(final Map items) { 708 709 BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable () { 711 public void run() { 712 handleUpdateSelection(items); 713 } 714 }); 715 } 716 722 protected Object [] filter(ViewerFilter[] filters, Object [] elements) { 723 if (filters != null) { 724 ArrayList filtered = new ArrayList (elements.length); 725 for (int i = 0; i < elements.length; i++) { 726 boolean add = true; 727 for (int j = 0; j < filters.length; j++) { 728 add = filters[j].select(null, null, elements[i]); 729 if (!add) 730 break; 731 } 732 if (add) 733 filtered.add(elements[i]); 734 } 735 return filtered.toArray(); 736 } 737 return elements; 738 } 739 740 private Object [] getTreeChildren(Object element) { 741 return filter(fTreeViewer.getFilters(), fTreeContentProvider.getChildren(element)); 742 } 743 744 private Object [] getListElements(Object element) { 745 return filter(fListViewer.getFilters(), fListContentProvider.getElements(element)); 746 } 747 748 public Set getWhiteCheckedTreeItems() { 749 return new HashSet (fWhiteCheckedTreeItems); 750 } 751 752 private void handleUpdateSelection(Map items) { 753 Iterator keyIterator= items.keySet().iterator(); 754 755 while (keyIterator.hasNext()) { 757 Object key= keyIterator.next(); 758 List selections= (List ) items.get(key); 760 if (selections.size() == 0) 761 fCheckedStateStore.remove(key); 763 else { 764 fCheckedStateStore.put(key, selections); 765 Object parent= fTreeContentProvider.getParent(key); 767 if (parent != null) { 768 addToHierarchyToCheckedStore(parent); 769 } 770 } 771 } 772 773 keyIterator= items.keySet().iterator(); 775 776 while (keyIterator.hasNext()) { 777 Object key= keyIterator.next(); 778 updateHierarchy(key); 779 if (fCurrentTreeSelection != null && fCurrentTreeSelection.equals(key)) { 780 fListViewer.setAllChecked(false); 781 fListViewer.setCheckedElements(((List ) items.get(key)).toArray()); 782 } 783 } 784 } 785 786 789 public boolean isTreeItemGreyChecked(Object object) { 790 return fTreeViewer.getGrayed(object); 791 } 792 793 796 public void expandTreeToLevel(Object object, int level) { 797 fTreeViewer.expandToLevel(object, level); 798 } 799 802 public void setTreeSelection(ISelection selection) { 803 fTreeViewer.setSelection(selection); 804 } 805 } 806 | Popular Tags |