001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.jarpackager;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.HashSet;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Map;
018: import java.util.Set;
019:
020: import org.eclipse.swt.SWT;
021: import org.eclipse.swt.custom.BusyIndicator;
022: import org.eclipse.swt.layout.GridData;
023: import org.eclipse.swt.layout.GridLayout;
024: import org.eclipse.swt.widgets.Composite;
025: import org.eclipse.swt.widgets.Table;
026: import org.eclipse.swt.widgets.Tree;
027:
028: import org.eclipse.jface.viewers.CheckStateChangedEvent;
029: import org.eclipse.jface.viewers.CheckboxTableViewer;
030: import org.eclipse.jface.viewers.CheckboxTreeViewer;
031: import org.eclipse.jface.viewers.ICheckStateListener;
032: import org.eclipse.jface.viewers.ILabelProvider;
033: import org.eclipse.jface.viewers.ISelection;
034: import org.eclipse.jface.viewers.ISelectionChangedListener;
035: import org.eclipse.jface.viewers.IStructuredContentProvider;
036: import org.eclipse.jface.viewers.IStructuredSelection;
037: import org.eclipse.jface.viewers.ITreeContentProvider;
038: import org.eclipse.jface.viewers.ITreeViewerListener;
039: import org.eclipse.jface.viewers.SelectionChangedEvent;
040: import org.eclipse.jface.viewers.StructuredSelection;
041: import org.eclipse.jface.viewers.TreeExpansionEvent;
042: import org.eclipse.jface.viewers.ViewerComparator;
043: import org.eclipse.jface.viewers.ViewerFilter;
044:
045: /**
046: * Combines a CheckboxTreeViewer and CheckboxListViewer.
047: * All viewer selection-driven interactions are handled within this viewer
048: */
049: public class CheckboxTreeAndListGroup implements ICheckStateListener,
050: ISelectionChangedListener, ITreeViewerListener {
051:
052: private Object fRoot;
053: private Object fCurrentTreeSelection;
054: private List fExpandedTreeNodes = new ArrayList();
055: private Map fCheckedStateStore = new HashMap(9);
056: private List fWhiteCheckedTreeItems = new ArrayList();
057: private List fListeners = new ArrayList();
058:
059: private ITreeContentProvider fTreeContentProvider;
060: private IStructuredContentProvider fListContentProvider;
061: private ILabelProvider fTreeLabelProvider;
062: private ILabelProvider fListLabelProvider;
063:
064: // widgets
065: private CheckboxTreeViewer fTreeViewer;
066: private CheckboxTableViewer fListViewer;
067:
068: /**
069: * Creates an instance of this class. Use this constructor if you wish to specify
070: * the width and/or height of the combined widget (to only hardcode one of the
071: * sizing dimensions, specify the other dimension's value as -1)
072: */
073: public CheckboxTreeAndListGroup(Composite parent,
074: Object rootObject,
075: ITreeContentProvider treeContentProvider,
076: ILabelProvider treeLabelProvider,
077: IStructuredContentProvider listContentProvider,
078: ILabelProvider listLabelProvider, int style, int width,
079: int height) {
080: fRoot = rootObject;
081: fTreeContentProvider = treeContentProvider;
082: fListContentProvider = listContentProvider;
083: fTreeLabelProvider = treeLabelProvider;
084: fListLabelProvider = listLabelProvider;
085: createContents(parent, width, height, style);
086: }
087:
088: /**
089: * This method must be called just before this window becomes visible.
090: */
091: public void aboutToOpen() {
092: determineWhiteCheckedDescendents(fRoot);
093: checkNewTreeElements(getTreeChildren(fRoot));
094: fCurrentTreeSelection = null;
095:
096: //select the first element in the list
097: Object[] elements = getTreeChildren(fRoot);
098: Object primary = elements.length > 0 ? elements[0] : null;
099: if (primary != null) {
100: fTreeViewer.setSelection(new StructuredSelection(primary));
101: }
102: fTreeViewer.getControl().setFocus();
103: }
104:
105: /**
106: * Adds the passed listener to self's collection of clients
107: * that listen for changes to element checked states
108: *
109: * @param listener ICheckStateListener
110: */
111: public void addCheckStateListener(ICheckStateListener listener) {
112: fListeners.add(listener);
113: }
114:
115: /**
116: * Adds the receiver and all of it's ancestors to the checkedStateStore if they
117: * are not already there.
118: */
119: private void addToHierarchyToCheckedStore(Object treeElement) {
120:
121: // if this tree element is already gray then its ancestors all are as well
122: 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:
130: /**
131: * Returns a boolean indicating whether all children of the passed tree element
132: * are currently white-checked
133: *
134: * @return boolean
135: * @param treeElement java.lang.Object
136: */
137: protected boolean areAllChildrenWhiteChecked(Object treeElement) {
138: Object[] children = getTreeChildren(treeElement);
139: for (int i = 0; i < children.length; ++i) {
140: if (!fWhiteCheckedTreeItems.contains(children[i]))
141: return false;
142: }
143:
144: return true;
145: }
146:
147: /**
148: * Returns a boolean indicating whether all list elements associated with
149: * the passed tree element are currently checked
150: *
151: * @return boolean
152: * @param treeElement java.lang.Object
153: */
154: protected boolean areAllElementsChecked(Object treeElement) {
155: List checkedElements = (List) fCheckedStateStore
156: .get(treeElement);
157: if (checkedElements == null) // ie.- tree item not even gray-checked
158: return false;
159:
160: return getListItemsSize(treeElement) == checkedElements.size();
161: }
162:
163: /**
164: * Iterates through the passed elements which are being realized for the first
165: * time and check each one in the tree viewer as appropriate
166: */
167: protected void checkNewTreeElements(Object[] elements) {
168: for (int i = 0; i < elements.length; ++i) {
169: Object currentElement = elements[i];
170: boolean checked = fCheckedStateStore
171: .containsKey(currentElement);
172: fTreeViewer.setChecked(currentElement, checked);
173: fTreeViewer
174: .setGrayed(currentElement, checked
175: && !fWhiteCheckedTreeItems
176: .contains(currentElement));
177: }
178: }
179:
180: /**
181: * An item was checked in one of self's two views. Determine which
182: * view this occurred in and delegate appropriately
183: *
184: * @param event CheckStateChangedEvent
185: */
186: public void checkStateChanged(final CheckStateChangedEvent event) {
187:
188: //Potentially long operation - show a busy cursor
189: BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(),
190: new Runnable() {
191: public void run() {
192: if (event.getCheckable().equals(fTreeViewer))
193: treeItemChecked(event.getElement(), event
194: .getChecked());
195: else
196: listItemChecked(event.getElement(), event
197: .getChecked(), true);
198:
199: notifyCheckStateChangeListeners(event);
200: }
201: });
202: }
203:
204: /**
205: * Lay out and initialize self's visual components.
206: *
207: * @param parent org.eclipse.swt.widgets.Composite
208: * @param width int
209: * @param height int
210: */
211: protected void createContents(Composite parent, int width,
212: int height, int style) {
213: // group pane
214: Composite composite = new Composite(parent, style);
215: GridLayout layout = new GridLayout();
216: layout.numColumns = 2;
217: layout.makeColumnsEqualWidth = true;
218: layout.marginHeight = 0;
219: layout.marginWidth = 0;
220: composite.setLayout(layout);
221: composite.setLayoutData(new GridData(GridData.FILL_BOTH));
222:
223: createTreeViewer(composite, width / 2, height);
224: createListViewer(composite, width / 2, height);
225:
226: initialize();
227: }
228:
229: /**
230: * Creates this group's list viewer.
231: */
232: protected void createListViewer(Composite parent, int width,
233: int height) {
234: fListViewer = CheckboxTableViewer.newCheckList(parent,
235: SWT.BORDER);
236: fListViewer.setUseHashlookup(true);
237: GridData data = new GridData(GridData.FILL_BOTH);
238: data.widthHint = width;
239: data.heightHint = height;
240: fListViewer.getTable().setLayoutData(data);
241: fListViewer.setContentProvider(fListContentProvider);
242: fListViewer.setLabelProvider(fListLabelProvider);
243: fListViewer.addCheckStateListener(this );
244: }
245:
246: /**
247: * Creates this group's tree viewer.
248: */
249: protected void createTreeViewer(Composite parent, int width,
250: int height) {
251: Tree tree = new Tree(parent, SWT.CHECK | SWT.BORDER);
252: GridData data = new GridData(GridData.FILL_BOTH);
253: data.widthHint = width;
254: data.heightHint = height;
255: tree.setLayoutData(data);
256:
257: fTreeViewer = new CheckboxTreeViewer(tree);
258: fTreeViewer.setUseHashlookup(true);
259: fTreeViewer.setContentProvider(fTreeContentProvider);
260: fTreeViewer.setLabelProvider(fTreeLabelProvider);
261: fTreeViewer.addTreeListener(this );
262: fTreeViewer.addCheckStateListener(this );
263: fTreeViewer.addSelectionChangedListener(this );
264: }
265:
266: /**
267: * Returns a boolean indicating whether the passed tree element should be
268: * at LEAST gray-checked. Note that this method does not consider whether
269: * it should be white-checked, so a specified tree item which should be
270: * white-checked will result in a <code>true</code> answer from this method.
271: * To determine whether a tree item should be white-checked use method
272: * #determineShouldBeWhiteChecked(Object).
273: *
274: * @param treeElement java.lang.Object
275: * @return boolean
276: * @see #determineShouldBeWhiteChecked(java.lang.Object)
277: */
278: protected boolean determineShouldBeAtLeastGrayChecked(
279: Object treeElement) {
280: // if any list items associated with treeElement are checked then it
281: // retains its gray-checked status regardless of its children
282: List checked = (List) fCheckedStateStore.get(treeElement);
283: if (checked != null && (!checked.isEmpty()))
284: return true;
285:
286: // if any children of treeElement are still gray-checked then treeElement
287: // must remain gray-checked as well
288: Object[] children = getTreeChildren(treeElement);
289: for (int i = 0; i < children.length; ++i) {
290: if (fCheckedStateStore.containsKey(children[i]))
291: return true;
292: }
293:
294: return false;
295: }
296:
297: /**
298: * Returns a boolean indicating whether the passed tree item should be
299: * white-checked.
300: *
301: * @return boolean
302: * @param treeElement java.lang.Object
303: */
304: protected boolean determineShouldBeWhiteChecked(Object treeElement) {
305: return areAllChildrenWhiteChecked(treeElement)
306: && areAllElementsChecked(treeElement);
307: }
308:
309: /**
310: * Recursively adds appropriate tree elements to the collection of
311: * known white-checked tree elements.
312: *
313: * @param treeElement java.lang.Object
314: */
315: protected void determineWhiteCheckedDescendents(Object treeElement) {
316: // always go through all children first since their white-checked
317: // statuses will be needed to determine the white-checked status for
318: // this tree element
319: Object[] children = getTreeChildren(treeElement);
320: for (int i = 0; i < children.length; ++i)
321: determineWhiteCheckedDescendents(children[i]);
322:
323: // now determine the white-checked status for this tree element
324: if (determineShouldBeWhiteChecked(treeElement))
325: setWhiteChecked(treeElement, true);
326: }
327:
328: /**
329: * Causes the tree viewer to expand all its items
330: */
331: public void expandAll() {
332: fTreeViewer.expandAll();
333: }
334:
335: /**
336: * Answers a flat collection of all of the checked elements in the
337: * list portion of self
338: *
339: * @return java.util.Vector
340: */
341: public Iterator getAllCheckedListItems() {
342: Set result = new HashSet();
343: Iterator listCollectionsEnum = fCheckedStateStore.values()
344: .iterator();
345: while (listCollectionsEnum.hasNext())
346: result.addAll((List) listCollectionsEnum.next());
347: return result.iterator();
348: }
349:
350: /**
351: * Answer a collection of all of the checked elements in the tree portion
352: * of self
353: *
354: * @return java.util.Vector
355: */
356: public Set getAllCheckedTreeItems() {
357: return new HashSet(fCheckedStateStore.keySet());
358: }
359:
360: /**
361: * Answers the number of elements that have been checked by the
362: * user.
363: *
364: * @return int
365: */
366: public int getCheckedElementCount() {
367: return fCheckedStateStore.size();
368: }
369:
370: /**
371: * Returns a count of the number of list items associated with a
372: * given tree item.
373: *
374: * @return int
375: * @param treeElement java.lang.Object
376: */
377: protected int getListItemsSize(Object treeElement) {
378: Object[] elements = getListElements(treeElement);
379: return elements.length;
380: }
381:
382: /**
383: * Gets the table that displays the folder content
384: *
385: * @return the table used to show the list
386: */
387: public Table getTable() {
388: return fListViewer.getTable();
389: }
390:
391: /**
392: * Gets the tree that displays the list for a folder
393: *
394: * @return the tree used to show the folders
395: */
396: public Tree getTree() {
397: return fTreeViewer.getTree();
398: }
399:
400: /**
401: * Adds the given filter to the tree viewer and
402: * triggers refiltering and resorting of the elements.
403: *
404: * @param filter a viewer filter
405: */
406: public void addTreeFilter(ViewerFilter filter) {
407: fTreeViewer.addFilter(filter);
408: }
409:
410: /**
411: * Adds the given filter to the list viewer and
412: * triggers refiltering and resorting of the elements.
413: *
414: * @param filter a viewer filter
415: */
416: public void addListFilter(ViewerFilter filter) {
417: fListViewer.addFilter(filter);
418: }
419:
420: /**
421: * Logically gray-check all ancestors of treeItem by ensuring that they
422: * appear in the checked table
423: */
424: protected void grayCheckHierarchy(Object treeElement) {
425:
426: // if this tree element is already gray then its ancestors all are as well
427: if (fCheckedStateStore.containsKey(treeElement))
428: return; // no need to proceed upwards from here
429:
430: fCheckedStateStore.put(treeElement, new ArrayList());
431: if (determineShouldBeWhiteChecked(treeElement)) {
432: setWhiteChecked(treeElement, true);
433: }
434: Object parent = fTreeContentProvider.getParent(treeElement);
435: if (parent != null)
436: grayCheckHierarchy(parent);
437: }
438:
439: /**
440: * Sets the initial checked state of the passed list element to true.
441: */
442: public void initialCheckListItem(Object element) {
443: Object parent = fTreeContentProvider.getParent(element);
444: fCurrentTreeSelection = parent;
445: //As this is not done from the UI then set the box for updating from the selection to false
446: listItemChecked(element, true, false);
447: updateHierarchy(parent);
448: }
449:
450: /**
451: * Sets the initial checked state of the passed element to true,
452: * as well as to all of its children and associated list elements
453: */
454: public void initialCheckTreeItem(Object element) {
455: treeItemChecked(element, true);
456: }
457:
458: /**
459: * Initializes this group's viewers after they have been laid out.
460: */
461: protected void initialize() {
462: fTreeViewer.setInput(fRoot);
463: }
464:
465: /**
466: * Callback that's invoked when the checked status of an item in the list
467: * is changed by the user. Do not try and update the hierarchy if we are building the
468: * initial list.
469: */
470: protected void listItemChecked(Object listElement, boolean state,
471: boolean updatingFromSelection) {
472: List checkedListItems = (List) fCheckedStateStore
473: .get(fCurrentTreeSelection);
474:
475: if (state) {
476: if (checkedListItems == null) {
477: // since the associated tree item has gone from 0 -> 1 checked
478: // list items, tree checking may need to be updated
479: grayCheckHierarchy(fCurrentTreeSelection);
480: checkedListItems = (List) fCheckedStateStore
481: .get(fCurrentTreeSelection);
482: }
483: checkedListItems.add(listElement);
484: } else {
485: checkedListItems.remove(listElement);
486: if (checkedListItems.isEmpty()) {
487: // since the associated tree item has gone from 1 -> 0 checked
488: // list items, tree checking may need to be updated
489: ungrayCheckHierarchy(fCurrentTreeSelection);
490: }
491: }
492:
493: if (updatingFromSelection)
494: updateHierarchy(fCurrentTreeSelection);
495: }
496:
497: /**
498: * Notifies all checked state listeners that the passed element has had
499: * its checked state changed to the passed state
500: */
501: protected void notifyCheckStateChangeListeners(
502: CheckStateChangedEvent event) {
503: Iterator listenersEnum = fListeners.iterator();
504: while (listenersEnum.hasNext())
505: ((ICheckStateListener) listenersEnum.next())
506: .checkStateChanged(event);
507: }
508:
509: /**
510: *Sets the contents of the list viewer based upon the specified selected
511: *tree element. This also includes checking the appropriate list items.
512: *
513: *@param treeElement java.lang.Object
514: */
515: protected void populateListViewer(final Object treeElement) {
516: if (treeElement == fCurrentTreeSelection)
517: return;
518: fCurrentTreeSelection = treeElement;
519: fListViewer.setInput(treeElement);
520: List listItemsToCheck = (List) fCheckedStateStore
521: .get(treeElement);
522:
523: if (listItemsToCheck != null) {
524: Iterator listItemsEnum = listItemsToCheck.iterator();
525: while (listItemsEnum.hasNext())
526: fListViewer.setChecked(listItemsEnum.next(), true);
527: }
528: }
529:
530: /**
531: * Removes the passed listener from self's collection of clients
532: * that listen for changes to element checked states
533: *
534: * @param listener ICheckStateListener
535: */
536: public void removeCheckStateListener(ICheckStateListener listener) {
537: fListeners.remove(listener);
538: }
539:
540: /**
541: * Handles the selection of an item in the tree viewer
542: *
543: * @param event ISelection
544: */
545: public void selectionChanged(final SelectionChangedEvent event) {
546: BusyIndicator.showWhile(getTable().getShell().getDisplay(),
547: new Runnable() {
548: public void run() {
549: IStructuredSelection selection = (IStructuredSelection) event
550: .getSelection();
551: Object selectedElement = selection
552: .getFirstElement();
553: if (selectedElement == null) {
554: fCurrentTreeSelection = null;
555: fListViewer.setInput(fCurrentTreeSelection);
556: return;
557: }
558: populateListViewer(selectedElement);
559: }
560: });
561: }
562:
563: /**
564: * Selects or deselect all of the elements in the tree depending on the value of the selection
565: * boolean. Be sure to update the displayed files as well.
566: */
567: public void setAllSelections(final boolean selection) {
568:
569: //Potentially long operation - show a busy cursor
570: BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(),
571: new Runnable() {
572: public void run() {
573: setTreeChecked(fRoot, selection);
574: fListViewer.setAllChecked(selection);
575: }
576: });
577: }
578:
579: /**
580: * Sets the list viewer's providers to those passed
581: *
582: * @param contentProvider ITreeContentProvider
583: * @param labelProvider ILabelProvider
584: */
585: public void setListProviders(
586: IStructuredContentProvider contentProvider,
587: ILabelProvider labelProvider) {
588: fListViewer.setContentProvider(contentProvider);
589: fListViewer.setLabelProvider(labelProvider);
590: }
591:
592: /**
593: * Sets the sorter that is to be applied to self's list viewer
594: */
595: public void setListComparator(ViewerComparator comparator) {
596: fListViewer.setComparator(comparator);
597: }
598:
599: /**
600: * Sets the root of the widget to be new Root. Regenerate all of the tables and lists from this
601: * value.
602: *
603: * @param newRoot
604: */
605: public void setRoot(Object newRoot) {
606: this .fRoot = newRoot;
607: initialize();
608: }
609:
610: /**
611: * Sets the checked state of the passed tree element appropriately, and
612: * do so recursively to all of its child tree elements as well
613: */
614: protected void setTreeChecked(Object treeElement, boolean state) {
615:
616: if (treeElement.equals(fCurrentTreeSelection)) {
617: fListViewer.setAllChecked(state);
618: }
619:
620: if (state) {
621: Object[] listItems = getListElements(treeElement);
622: List listItemsChecked = new ArrayList();
623: for (int i = 0; i < listItems.length; ++i)
624: listItemsChecked.add(listItems[i]);
625:
626: fCheckedStateStore.put(treeElement, listItemsChecked);
627: } else
628: fCheckedStateStore.remove(treeElement);
629:
630: setWhiteChecked(treeElement, state);
631: fTreeViewer.setChecked(treeElement, state);
632: fTreeViewer.setGrayed(treeElement, false);
633:
634: // now logically check/uncheck all children as well
635: Object[] children = getTreeChildren(treeElement);
636: for (int i = 0; i < children.length; ++i) {
637: setTreeChecked(children[i], state);
638: }
639: }
640:
641: /**
642: * Sets the tree viewer's providers to those passed
643: *
644: * @param contentProvider ITreeContentProvider
645: * @param labelProvider ILabelProvider
646: */
647: public void setTreeProviders(ITreeContentProvider contentProvider,
648: ILabelProvider labelProvider) {
649: fTreeViewer.setContentProvider(contentProvider);
650: fTreeViewer.setLabelProvider(labelProvider);
651: }
652:
653: /**
654: * Sets the sorter that is to be applied to self's tree viewer
655: */
656: public void setTreeComparator(ViewerComparator sorter) {
657: fTreeViewer.setComparator(sorter);
658: }
659:
660: /**
661: * Adjusts the collection of references to white-checked tree elements appropriately.
662: *
663: * @param treeElement java.lang.Object
664: * @param isWhiteChecked boolean
665: */
666: protected void setWhiteChecked(Object treeElement,
667: boolean isWhiteChecked) {
668: if (isWhiteChecked) {
669: if (!fWhiteCheckedTreeItems.contains(treeElement))
670: fWhiteCheckedTreeItems.add(treeElement);
671: } else
672: fWhiteCheckedTreeItems.remove(treeElement);
673: }
674:
675: /**
676: * Handle the collapsing of an element in a tree viewer
677: */
678: public void treeCollapsed(TreeExpansionEvent event) {
679: // We don't need to do anything with this
680: }
681:
682: /**
683: * Handles the expansionsion of an element in a tree viewer
684: */
685: public void treeExpanded(TreeExpansionEvent event) {
686:
687: Object item = event.getElement();
688:
689: // First see if the children need to be given their checked state at all. If they've
690: // already been realized then this won't be necessary
691: if (!fExpandedTreeNodes.contains(item)) {
692: fExpandedTreeNodes.add(item);
693: checkNewTreeElements(getTreeChildren(item));
694: }
695: }
696:
697: /**
698: * Callback that's invoked when the checked status of an item in the tree
699: * is changed by the user.
700: */
701: protected void treeItemChecked(Object treeElement, boolean state) {
702:
703: // recursively adjust all child tree elements appropriately
704: setTreeChecked(treeElement, state);
705:
706: Object parent = fTreeContentProvider.getParent(treeElement);
707: if (parent == null)
708: return;
709:
710: // now update upwards in the tree hierarchy
711: if (state)
712: grayCheckHierarchy(parent);
713: else
714: ungrayCheckHierarchy(parent);
715:
716: updateHierarchy(treeElement);
717: }
718:
719: /**
720: * Logically un-gray-check all ancestors of treeItem iff appropriate.
721: */
722: protected void ungrayCheckHierarchy(Object treeElement) {
723: if (!determineShouldBeAtLeastGrayChecked(treeElement))
724: fCheckedStateStore.remove(treeElement);
725:
726: Object parent = fTreeContentProvider.getParent(treeElement);
727: if (parent != null)
728: ungrayCheckHierarchy(parent);
729: }
730:
731: /**
732: * Sets the checked state of self and all ancestors appropriately
733: */
734: protected void updateHierarchy(Object treeElement) {
735:
736: boolean whiteChecked = determineShouldBeWhiteChecked(treeElement);
737: boolean shouldBeAtLeastGray = determineShouldBeAtLeastGrayChecked(treeElement);
738:
739: fTreeViewer.setChecked(treeElement, whiteChecked
740: || shouldBeAtLeastGray);
741: setWhiteChecked(treeElement, whiteChecked);
742: if (whiteChecked)
743: fTreeViewer.setGrayed(treeElement, false);
744: else
745: fTreeViewer.setGrayed(treeElement, shouldBeAtLeastGray);
746:
747: // proceed up the tree element hierarchy
748: Object parent = fTreeContentProvider.getParent(treeElement);
749: if (parent != null) {
750: updateHierarchy(parent);
751: }
752: }
753:
754: /**
755: * Update the selections of the tree elements in items to reflect the new
756: * selections provided.
757: *
758: * @param items with keys of Object (the tree element) and values of List (the selected
759: * list elements).
760: */
761: public void updateSelections(final Map items) {
762:
763: //Potentially long operation - show a busy cursor
764: BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(),
765: new Runnable() {
766: public void run() {
767: handleUpdateSelection(items);
768: }
769: });
770: }
771:
772: /**
773: * Returns the result of running the given elements through the filters.
774: *
775: * @param elements the elements to filter
776: * @return only the elements which all filters accept
777: */
778: protected Object[] filter(ViewerFilter[] filters, Object[] elements) {
779: if (filters != null) {
780: ArrayList filtered = new ArrayList(elements.length);
781: for (int i = 0; i < elements.length; i++) {
782: boolean add = true;
783: for (int j = 0; j < filters.length; j++) {
784: add = filters[j].select(null, null, elements[i]);
785: if (!add)
786: break;
787: }
788: if (add)
789: filtered.add(elements[i]);
790: }
791: return filtered.toArray();
792: }
793: return elements;
794: }
795:
796: private Object[] getTreeChildren(Object element) {
797: return filter(fTreeViewer.getFilters(), fTreeContentProvider
798: .getChildren(element));
799: }
800:
801: private Object[] getListElements(Object element) {
802: return filter(fListViewer.getFilters(), fListContentProvider
803: .getElements(element));
804: }
805:
806: public Set getWhiteCheckedTreeItems() {
807: return new HashSet(fWhiteCheckedTreeItems);
808: }
809:
810: private void handleUpdateSelection(Map items) {
811: Iterator keyIterator = items.keySet().iterator();
812:
813: //Update the store before the hierarchy to prevent updating parents before all of the children are done
814: while (keyIterator.hasNext()) {
815: Object key = keyIterator.next();
816: //Replace the items in the checked state store with those from the supplied items
817: List selections = (List) items.get(key);
818: if (selections.size() == 0)
819: //If it is empty remove it from the list
820: fCheckedStateStore.remove(key);
821: else {
822: fCheckedStateStore.put(key, selections);
823: // proceed up the tree element hierarchy
824: Object parent = fTreeContentProvider.getParent(key);
825: if (parent != null) {
826: addToHierarchyToCheckedStore(parent);
827: }
828: }
829: }
830:
831: //Now update hierarchies
832: keyIterator = items.keySet().iterator();
833:
834: while (keyIterator.hasNext()) {
835: Object key = keyIterator.next();
836: updateHierarchy(key);
837: if (fCurrentTreeSelection != null
838: && fCurrentTreeSelection.equals(key)) {
839: fListViewer.setAllChecked(false);
840: fListViewer.setCheckedElements(((List) items.get(key))
841: .toArray());
842: }
843: }
844: }
845:
846: /**
847: * Checks if an element is grey checked.
848: */
849: public boolean isTreeItemGreyChecked(Object object) {
850: return fTreeViewer.getGrayed(object);
851: }
852:
853: /**
854: * For a given element, expand its chidren to a level.
855: */
856: public void expandTreeToLevel(Object object, int level) {
857: fTreeViewer.expandToLevel(object, level);
858: }
859:
860: /**
861: * @param selection
862: */
863: public void setTreeSelection(ISelection selection) {
864: fTreeViewer.setSelection(selection);
865: }
866: }
|