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