1 11 package org.eclipse.ui.internal.editors.text; 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.swt.SWT; 23 import org.eclipse.swt.custom.BusyIndicator; 24 import org.eclipse.swt.layout.GridData; 25 import org.eclipse.swt.layout.GridLayout; 26 import org.eclipse.swt.widgets.Composite; 27 import org.eclipse.swt.widgets.Tree; 28 29 import org.eclipse.core.runtime.ListenerList; 30 import org.eclipse.core.runtime.SafeRunner; 31 32 import org.eclipse.jface.util.SafeRunnable; 33 import org.eclipse.jface.viewers.CheckStateChangedEvent; 34 import org.eclipse.jface.viewers.CheckboxTableViewer; 35 import org.eclipse.jface.viewers.CheckboxTreeViewer; 36 import org.eclipse.jface.viewers.ICheckStateListener; 37 import org.eclipse.jface.viewers.ILabelProvider; 38 import org.eclipse.jface.viewers.ISelectionChangedListener; 39 import org.eclipse.jface.viewers.IStructuredContentProvider; 40 import org.eclipse.jface.viewers.IStructuredSelection; 41 import org.eclipse.jface.viewers.ITreeContentProvider; 42 import org.eclipse.jface.viewers.ITreeViewerListener; 43 import org.eclipse.jface.viewers.SelectionChangedEvent; 44 import org.eclipse.jface.viewers.StructuredSelection; 45 import org.eclipse.jface.viewers.TreeExpansionEvent; 46 import org.eclipse.jface.viewers.ViewerComparator; 47 48 52 53 58 class SelectResourcesBlock implements ICheckStateListener, ISelectionChangedListener, ITreeViewerListener { 59 60 61 69 interface IElementFilter { 70 71 void filterElements(Collection elements) throws InterruptedException ; 72 73 void filterElements(Object [] elements) throws InterruptedException ; 74 } 75 76 77 private Object root; 78 79 private Object currentTreeSelection; 80 81 private Collection expandedTreeNodes= new HashSet (); 82 83 private Map checkedStateStore= new HashMap (9); 84 85 private Collection whiteCheckedTreeItems= new HashSet (); 86 87 private ListenerList listeners= new ListenerList(ListenerList.IDENTITY); 88 89 private ITreeContentProvider treeContentProvider; 90 91 private IStructuredContentProvider listContentProvider; 92 93 private ILabelProvider treeLabelProvider; 94 95 private ILabelProvider listLabelProvider; 96 97 private CheckboxTreeViewer treeViewer; 99 100 private CheckboxTableViewer listViewer; 101 102 private static int PREFERRED_HEIGHT= 150; 104 105 119 public SelectResourcesBlock(Composite parent, Object rootObject, ITreeContentProvider treeContentProvider, ILabelProvider treeLabelProvider, IStructuredContentProvider listContentProvider, ILabelProvider listLabelProvider, int style, boolean useHeightHint) { 120 121 root= rootObject; 122 this.treeContentProvider= treeContentProvider; 123 this.listContentProvider= listContentProvider; 124 this.treeLabelProvider= treeLabelProvider; 125 this.listLabelProvider= listLabelProvider; 126 createContents(parent, style, useHeightHint); 127 } 128 129 135 public void addCheckStateListener(ICheckStateListener listener) { 136 listeners.add(listener); 137 } 138 139 145 private void checkNewTreeElements(Object [] elements) { 146 for (int i= 0; i < elements.length; ++i) { 147 Object currentElement= elements[i]; 148 boolean checked= checkedStateStore.containsKey(currentElement); 149 treeViewer.setChecked(currentElement, checked); 150 treeViewer.setGrayed(currentElement, checked && !whiteCheckedTreeItems.contains(currentElement)); 151 } 152 } 153 154 161 public void checkStateChanged(final CheckStateChangedEvent event) { 162 163 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), new Runnable () { 165 public void run() { 166 if (event.getCheckable().equals(treeViewer)) 167 treeItemChecked(event.getElement(), event.getChecked()); 168 else 169 listItemChecked(event.getElement(), event.getChecked(), true); 170 171 notifyCheckStateChangeListeners(event); 172 } 173 }); 174 } 175 176 183 private void createContents(Composite parent, int style, boolean useHeightHint) { 184 Composite composite= new Composite(parent, style); 186 composite.setFont(parent.getFont()); 187 GridLayout layout= new GridLayout(); 188 layout.numColumns= 2; 189 layout.makeColumnsEqualWidth= true; 190 layout.marginHeight= 0; 191 layout.marginWidth= 0; 192 composite.setLayout(layout); 193 composite.setLayoutData(new GridData(GridData.FILL_BOTH)); 194 195 createTreeViewer(composite, useHeightHint); 196 createListViewer(composite, useHeightHint); 197 198 initialize(); 199 } 200 201 207 private void createListViewer(Composite parent, boolean useHeightHint) { 208 listViewer= CheckboxTableViewer.newCheckList(parent, SWT.BORDER); 209 GridData data= new GridData(GridData.FILL_BOTH); 210 if (useHeightHint) 211 data.heightHint= PREFERRED_HEIGHT; 212 listViewer.getTable().setLayoutData(data); 213 listViewer.getTable().setFont(parent.getFont()); 214 listViewer.setContentProvider(listContentProvider); 215 listViewer.setLabelProvider(listLabelProvider); 216 listViewer.addCheckStateListener(this); 217 } 218 219 225 private void createTreeViewer(Composite parent, boolean useHeightHint) { 226 Tree tree= new Tree(parent, SWT.CHECK | SWT.BORDER); 227 GridData data= new GridData(GridData.FILL_BOTH); 228 if (useHeightHint) 229 data.heightHint= PREFERRED_HEIGHT; 230 tree.setLayoutData(data); 231 tree.setFont(parent.getFont()); 232 233 treeViewer= new CheckboxTreeViewer(tree); 234 treeViewer.setUseHashlookup(true); 235 treeViewer.setContentProvider(treeContentProvider); 236 treeViewer.setLabelProvider(treeLabelProvider); 237 treeViewer.addTreeListener(this); 238 treeViewer.addCheckStateListener(this); 239 treeViewer.addSelectionChangedListener(this); 240 } 241 242 252 private boolean determineShouldBeAtLeastGrayChecked(Object treeElement) { 253 List checked= (List ) checkedStateStore.get(treeElement); 256 if (checked != null && (!checked.isEmpty())) 257 return true; 258 259 if (expandedTreeNodes.contains(treeElement)) { 263 Object [] children= treeContentProvider.getChildren(treeElement); 264 for (int i= 0; i < children.length; ++i) { 265 if (checkedStateStore.containsKey(children[i])) 266 return true; 267 } 268 } 269 270 return false; 271 } 272 273 278 private void expandTreeElement(final Object element) { 279 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), new Runnable () { 280 public void run() { 281 282 if (expandedTreeNodes.contains(element)) 286 checkNewTreeElements(treeContentProvider.getChildren(element)); 287 else { 288 289 expandedTreeNodes.add(element); 290 if (whiteCheckedTreeItems.contains(element)) { 291 Object [] children= treeContentProvider.getChildren(element); 294 for (int i= 0; i < children.length; ++i) { 295 if (!whiteCheckedTreeItems.contains(children[i])) { 296 Object child= children[i]; 297 setWhiteChecked(child, true); 298 treeViewer.setChecked(child, true); 299 checkedStateStore.put(child, new ArrayList ()); 300 } 301 } 302 303 setListForWhiteSelection(element); 305 } 306 } 307 308 } 309 }); 310 } 311 312 322 private void findAllSelectedListElements(Object treeElement, String parentLabel, boolean addAll, IElementFilter filter) throws InterruptedException { 323 324 String fullLabel= null; 325 326 if (addAll) 327 filter.filterElements(listContentProvider.getElements(treeElement)); 328 else { if (checkedStateStore.containsKey(treeElement)) 330 filter.filterElements((Collection ) checkedStateStore.get(treeElement)); 331 } 332 333 Object [] treeChildren= treeContentProvider.getChildren(treeElement); 334 for (int i= 0; i < treeChildren.length; i++) { 335 Object child= treeChildren[i]; 336 if (addAll) 337 findAllSelectedListElements(child, fullLabel, true, filter); 338 else { if (checkedStateStore.containsKey(child)) 340 findAllSelectedListElements(child, fullLabel, whiteCheckedTreeItems.contains(child), filter); 341 } 342 343 } 344 } 345 346 354 private void findAllWhiteCheckedItems(Object treeElement, Collection result) { 355 356 if (whiteCheckedTreeItems.contains(treeElement)) 357 result.add(treeElement); 358 else { 359 Collection listChildren= (Collection ) checkedStateStore.get(treeElement); 360 if (listChildren == null) 363 return; 364 result.addAll(listChildren); 365 Object [] children= treeContentProvider.getChildren(treeElement); 366 for (int i= 0; i < children.length; ++i) { 367 findAllWhiteCheckedItems(children[i], result); 368 } 369 } 370 } 371 372 380 private void getAllCheckedListItems(IElementFilter filter) throws InterruptedException { 381 Object [] children= treeContentProvider.getChildren(root); 383 for (int i= 0; i < children.length; ++i) { 384 findAllSelectedListElements(children[i], null, whiteCheckedTreeItems.contains(children[i]), filter); 385 } 386 } 387 388 394 public List getAllCheckedListItems() { 395 396 final ArrayList returnValue= new ArrayList (); 397 398 IElementFilter passThroughFilter= new IElementFilter() { 399 400 public void filterElements(Collection elements) throws InterruptedException { 401 returnValue.addAll(elements); 402 } 403 404 public void filterElements(Object [] elements) throws InterruptedException { 405 for (int i= 0; i < elements.length; i++) { 406 returnValue.add(elements[i]); 407 } 408 } 409 }; 410 411 try { 412 getAllCheckedListItems(passThroughFilter); 413 } catch (InterruptedException exception) { 414 return new ArrayList (); 415 } 416 return returnValue; 417 418 } 419 420 427 public List getAllWhiteCheckedItems() { 428 429 List result= new ArrayList (); 430 431 Object [] children= treeContentProvider.getChildren(root); 434 for (int i= 0; i < children.length; ++i) { 435 findAllWhiteCheckedItems(children[i], result); 436 } 437 438 return result; 439 } 440 441 447 private void grayCheckHierarchy(Object treeElement) { 448 449 expandTreeElement(treeElement); 451 452 if (checkedStateStore.containsKey(treeElement)) 455 return; 457 checkedStateStore.put(treeElement, new ArrayList ()); 458 Object parent= treeContentProvider.getParent(treeElement); 459 if (parent != null) 460 grayCheckHierarchy(parent); 461 } 462 463 469 private void grayUpdateHierarchy(Object treeElement) { 470 471 boolean shouldBeAtLeastGray= determineShouldBeAtLeastGrayChecked(treeElement); 472 473 treeViewer.setGrayChecked(treeElement, shouldBeAtLeastGray); 474 475 if (whiteCheckedTreeItems.contains(treeElement)) 476 whiteCheckedTreeItems.remove(treeElement); 477 478 Object parent= treeContentProvider.getParent(treeElement); 480 if (parent != null) { 481 grayUpdateHierarchy(parent); 482 } 483 } 484 485 public void selectAndReveal(Object treeElement) { 486 treeViewer.reveal(treeElement); 487 IStructuredSelection selection= new StructuredSelection(treeElement); 488 treeViewer.setSelection(selection); 489 } 490 491 494 private void initialize() { 495 treeViewer.setInput(root); 496 this.expandedTreeNodes= new ArrayList (); 497 this.expandedTreeNodes.add(root); 498 499 } 500 501 511 private void listItemChecked(Object listElement, boolean state, boolean updatingFromSelection) { 512 List checkedListItems= (List ) checkedStateStore.get(currentTreeSelection); 513 if (!expandedTreeNodes.contains(currentTreeSelection)) 516 expandTreeElement(currentTreeSelection); 517 518 if (state) { 519 if (checkedListItems == null) { 520 grayCheckHierarchy(currentTreeSelection); 523 checkedListItems= (List ) checkedStateStore.get(currentTreeSelection); 524 } 525 checkedListItems.add(listElement); 526 } else { 527 checkedListItems.remove(listElement); 528 if (checkedListItems.isEmpty()) { 529 ungrayCheckHierarchy(currentTreeSelection); 532 } 533 } 534 535 if (checkedListItems.size() > 0) 537 checkedStateStore.put(currentTreeSelection, checkedListItems); 538 if (updatingFromSelection) 539 grayUpdateHierarchy(currentTreeSelection); 540 } 541 542 547 private void notifyCheckStateChangeListeners(final CheckStateChangedEvent event) { 548 Object [] array= listeners.getListeners(); 549 for (int i= 0; i < array.length; i++) { 550 final ICheckStateListener l= (ICheckStateListener) array[i]; 551 SafeRunner.run(new SafeRunnable() { 552 public void run() { 553 l.checkStateChanged(event); 554 } 555 }); 556 } 557 } 558 559 565 private void populateListViewer(final Object treeElement) { 566 listViewer.setInput(treeElement); 567 568 if (!(expandedTreeNodes.contains(treeElement)) && whiteCheckedTreeItems.contains(treeElement)) { 571 572 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), new Runnable () { 574 public void run() { 575 setListForWhiteSelection(treeElement); 576 listViewer.setAllChecked(true); 577 } 578 }); 579 580 } else { 581 List listItemsToCheck= (List ) checkedStateStore.get(treeElement); 582 583 if (listItemsToCheck != null) { 584 Iterator listItemsEnum= listItemsToCheck.iterator(); 585 while (listItemsEnum.hasNext()) 586 listViewer.setChecked(listItemsEnum.next(), true); 587 } 588 } 589 } 590 591 599 private void primeHierarchyForSelection(Object item, Set selectedNodes) { 600 601 if (selectedNodes.contains(item)) 603 return; 604 605 checkedStateStore.put(item, new ArrayList ()); 606 607 expandedTreeNodes.add(item); 609 selectedNodes.add(item); 610 611 Object parent= treeContentProvider.getParent(item); 612 if (parent != null) 613 primeHierarchyForSelection(parent, selectedNodes); 614 } 615 616 622 public void removeCheckStateListener(ICheckStateListener listener) { 623 listeners.remove(listener); 624 } 625 626 631 public void selectionChanged(SelectionChangedEvent event) { 632 IStructuredSelection selection= (IStructuredSelection) event.getSelection(); 633 Object selectedElement= selection.getFirstElement(); 634 if (selectedElement == null) { 635 currentTreeSelection= null; 636 listViewer.setInput(currentTreeSelection); 637 return; 638 } 639 640 if (selectedElement != currentTreeSelection) 642 populateListViewer(selectedElement); 643 644 currentTreeSelection= selectedElement; 645 } 646 647 655 public void setAllSelections(final boolean selection) { 656 657 if (root == null) 659 return; 660 661 BusyIndicator.showWhile(treeViewer.getControl().getDisplay(), new Runnable () { 663 public void run() { 664 setTreeChecked(root, selection); 665 listViewer.setAllChecked(selection); 666 } 667 }); 668 } 669 670 676 private void setListForWhiteSelection(Object treeElement) { 677 678 Object [] listItems= listContentProvider.getElements(treeElement); 679 List listItemsChecked= new ArrayList (); 680 for (int i= 0; i < listItems.length; ++i) { 681 listItemsChecked.add(listItems[i]); 682 } 683 684 checkedStateStore.put(treeElement, listItemsChecked); 685 } 686 687 692 public void setListComparator(ViewerComparator comparator) { 693 listViewer.setComparator(comparator); 694 } 695 696 704 private void setTreeChecked(Object treeElement, boolean state) { 705 706 if (treeElement.equals(currentTreeSelection)) { 707 listViewer.setAllChecked(state); 708 } 709 710 if (state) { 711 setListForWhiteSelection(treeElement); 712 } else 713 checkedStateStore.remove(treeElement); 714 715 setWhiteChecked(treeElement, state); 716 treeViewer.setChecked(treeElement, state); 717 treeViewer.setGrayed(treeElement, false); 718 719 if (expandedTreeNodes.contains(treeElement)) { 722 Object [] children= treeContentProvider.getChildren(treeElement); 723 for (int i= 0; i < children.length; ++i) { 724 setTreeChecked(children[i], state); 725 } 726 } 727 } 728 729 734 public void setTreeComparator(ViewerComparator comparator) { 735 treeViewer.setComparator(comparator); 736 } 737 738 746 private void setWhiteChecked(Object treeElement, boolean isWhiteChecked) { 747 if (isWhiteChecked) { 748 if (!whiteCheckedTreeItems.contains(treeElement)) 749 whiteCheckedTreeItems.add(treeElement); 750 } else 751 whiteCheckedTreeItems.remove(treeElement); 752 } 753 754 759 public void treeCollapsed(TreeExpansionEvent event) { 760 } 762 763 768 public void treeExpanded(TreeExpansionEvent event) { 769 expandTreeElement(event.getElement()); 770 } 771 772 780 private void treeItemChecked(Object treeElement, boolean state) { 781 782 setTreeChecked(treeElement, state); 784 785 Object parent= treeContentProvider.getParent(treeElement); 786 if (parent == null) 787 return; 788 789 if (state) 791 grayCheckHierarchy(parent); 792 else 793 ungrayCheckHierarchy(parent); 794 795 grayUpdateHierarchy(parent); 797 } 798 799 805 private void ungrayCheckHierarchy(Object treeElement) { 806 if (!determineShouldBeAtLeastGrayChecked(treeElement)) 807 checkedStateStore.remove(treeElement); 808 809 Object parent= treeContentProvider.getParent(treeElement); 810 if (parent != null) 811 ungrayCheckHierarchy(parent); 812 } 813 814 824 public void updateSelections(Map items) { 825 this.listViewer.setAllChecked(false); 828 this.treeViewer.setCheckedElements(new Object [0]); 829 this.whiteCheckedTreeItems= new HashSet (); 830 Set selectedNodes= new HashSet (); 831 checkedStateStore= new HashMap (); 832 833 Iterator keyIterator= items.keySet().iterator(); 836 while (keyIterator.hasNext()) { 837 Object key= keyIterator.next(); 838 primeHierarchyForSelection(key, selectedNodes); 839 checkedStateStore.put(key, items.get(key)); 840 } 841 842 treeViewer.setCheckedElements(checkedStateStore.keySet().toArray()); 845 treeViewer.setGrayedElements(checkedStateStore.keySet().toArray()); 846 847 if (currentTreeSelection != null) { 849 Object displayItems= items.get(currentTreeSelection); 850 if (displayItems != null) 851 listViewer.setCheckedElements(((List ) displayItems).toArray()); 852 } 853 } 854 } 855 | Popular Tags |