PageRenderTime 41ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.jdt.ui.source_3.7.1.r371_v20110824-0800/org/eclipse/jdt/internal/ui/jarpackager/CheckboxTreeAndListGroup.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 846 lines | 456 code | 56 blank | 334 comment | 73 complexity | 3bbe610bd0baa29260c252e2cc2b2845 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2011 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.jdt.internal.ui.jarpackager;
  12. import java.util.ArrayList;
  13. import java.util.HashMap;
  14. import java.util.HashSet;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.util.Map;
  18. import java.util.Set;
  19. import org.eclipse.swt.SWT;
  20. import org.eclipse.swt.custom.BusyIndicator;
  21. import org.eclipse.swt.layout.GridData;
  22. import org.eclipse.swt.layout.GridLayout;
  23. import org.eclipse.swt.widgets.Composite;
  24. import org.eclipse.swt.widgets.Table;
  25. import org.eclipse.swt.widgets.Tree;
  26. import org.eclipse.jface.viewers.CheckStateChangedEvent;
  27. import org.eclipse.jface.viewers.CheckboxTableViewer;
  28. import org.eclipse.jface.viewers.CheckboxTreeViewer;
  29. import org.eclipse.jface.viewers.ICheckStateListener;
  30. import org.eclipse.jface.viewers.ILabelProvider;
  31. import org.eclipse.jface.viewers.ISelection;
  32. import org.eclipse.jface.viewers.ISelectionChangedListener;
  33. import org.eclipse.jface.viewers.IStructuredContentProvider;
  34. import org.eclipse.jface.viewers.IStructuredSelection;
  35. import org.eclipse.jface.viewers.ITreeContentProvider;
  36. import org.eclipse.jface.viewers.ITreeViewerListener;
  37. import org.eclipse.jface.viewers.SelectionChangedEvent;
  38. import org.eclipse.jface.viewers.StructuredSelection;
  39. import org.eclipse.jface.viewers.TreeExpansionEvent;
  40. import org.eclipse.jface.viewers.ViewerComparator;
  41. import org.eclipse.jface.viewers.ViewerFilter;
  42. /**
  43. * Combines a CheckboxTreeViewer and CheckboxListViewer.
  44. * All viewer selection-driven interactions are handled within this viewer
  45. */
  46. public class CheckboxTreeAndListGroup implements ICheckStateListener, ISelectionChangedListener, ITreeViewerListener {
  47. private Object fRoot;
  48. private Object fCurrentTreeSelection;
  49. private List<Object> fExpandedTreeNodes= new ArrayList<Object>();
  50. private Map<Object, List<Object>> fCheckedStateStore= new HashMap<Object, List<Object>>(9);
  51. private List<Object> fWhiteCheckedTreeItems= new ArrayList<Object>();
  52. private List<ICheckStateListener> fListeners= new ArrayList<ICheckStateListener>();
  53. private ITreeContentProvider fTreeContentProvider;
  54. private IStructuredContentProvider fListContentProvider;
  55. private ILabelProvider fTreeLabelProvider;
  56. private ILabelProvider fListLabelProvider;
  57. // widgets
  58. private CheckboxTreeViewer fTreeViewer;
  59. private CheckboxTableViewer fListViewer;
  60. /**
  61. * Creates an instance of this class. Use this constructor if you wish to specify
  62. * the width and/or height of the combined widget (to only hardcode one of the
  63. * sizing dimensions, specify the other dimension's value as -1)
  64. * @param parent parent composite
  65. * @param rootObject
  66. * @param treeContentProvider
  67. * @param treeLabelProvider
  68. * @param listContentProvider
  69. * @param listLabelProvider
  70. * @param style
  71. * @param width the width
  72. * @param height the height
  73. */
  74. public CheckboxTreeAndListGroup(
  75. Composite parent,
  76. Object rootObject,
  77. ITreeContentProvider treeContentProvider,
  78. ILabelProvider treeLabelProvider,
  79. IStructuredContentProvider listContentProvider,
  80. ILabelProvider listLabelProvider,
  81. int style,
  82. int width,
  83. int height) {
  84. fRoot= rootObject;
  85. fTreeContentProvider= treeContentProvider;
  86. fListContentProvider= listContentProvider;
  87. fTreeLabelProvider= treeLabelProvider;
  88. fListLabelProvider= listLabelProvider;
  89. createContents(parent, width, height, style);
  90. }
  91. /**
  92. * This method must be called just before this window becomes visible.
  93. */
  94. public void aboutToOpen() {
  95. determineWhiteCheckedDescendents(fRoot);
  96. checkNewTreeElements(getTreeChildren(fRoot));
  97. fCurrentTreeSelection= null;
  98. //select the first element in the list
  99. 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. /**
  107. * Adds the passed listener to self's collection of clients
  108. * that listen for changes to element checked states
  109. *
  110. * @param listener ICheckStateListener
  111. */
  112. public void addCheckStateListener(ICheckStateListener listener) {
  113. fListeners.add(listener);
  114. }
  115. /**
  116. * Adds the receiver and all of it's ancestors to the checkedStateStore if they
  117. * are not already there.
  118. * @param treeElement
  119. */
  120. private void addToHierarchyToCheckedStore(Object treeElement) {
  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<Object>());
  124. Object parent= fTreeContentProvider.getParent(treeElement);
  125. if (parent != null)
  126. addToHierarchyToCheckedStore(parent);
  127. }
  128. /**
  129. * Returns a boolean indicating whether all children of the passed tree element
  130. * are currently white-checked
  131. *
  132. * @return boolean
  133. * @param treeElement java.lang.Object
  134. */
  135. protected boolean areAllChildrenWhiteChecked(Object treeElement) {
  136. Object[] children= getTreeChildren(treeElement);
  137. for (int i= 0; i < children.length; ++i) {
  138. if (!fWhiteCheckedTreeItems.contains(children[i]))
  139. return false;
  140. }
  141. return true;
  142. }
  143. /**
  144. * Returns a boolean indicating whether all list elements associated with
  145. * the passed tree element are currently checked
  146. *
  147. * @return boolean
  148. * @param treeElement java.lang.Object
  149. */
  150. protected boolean areAllElementsChecked(Object treeElement) {
  151. List<Object> checkedElements= fCheckedStateStore.get(treeElement);
  152. if (checkedElements == null) // ie.- tree item not even gray-checked
  153. return false;
  154. return getListItemsSize(treeElement) == checkedElements.size();
  155. }
  156. /**
  157. * Iterates through the passed elements which are being realized for the first
  158. * time and check each one in the tree viewer as appropriate
  159. * @param elements
  160. */
  161. protected void checkNewTreeElements(Object[] elements) {
  162. for (int i= 0; i < elements.length; ++i) {
  163. Object currentElement= elements[i];
  164. boolean checked= fCheckedStateStore.containsKey(currentElement);
  165. fTreeViewer.setChecked(currentElement, checked);
  166. fTreeViewer.setGrayed(
  167. currentElement,
  168. checked && !fWhiteCheckedTreeItems.contains(currentElement));
  169. }
  170. }
  171. /**
  172. * An item was checked in one of self's two views. Determine which
  173. * view this occurred in and delegate appropriately
  174. *
  175. * @param event CheckStateChangedEvent
  176. */
  177. public void checkStateChanged(final CheckStateChangedEvent event) {
  178. //Potentially long operation - show a busy cursor
  179. BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable() {
  180. public void run() {
  181. if (event.getCheckable().equals(fTreeViewer))
  182. treeItemChecked(event.getElement(), event.getChecked());
  183. else
  184. listItemChecked(event.getElement(), event.getChecked(), true);
  185. notifyCheckStateChangeListeners(event);
  186. }
  187. });
  188. }
  189. /**
  190. * Lay out and initialize self's visual components.
  191. *
  192. * @param parent org.eclipse.swt.widgets.Composite
  193. * @param width int
  194. * @param height int
  195. * @param style
  196. */
  197. protected void createContents(
  198. Composite parent,
  199. int width,
  200. int height,
  201. int style) {
  202. // group pane
  203. Composite composite= new Composite(parent, style);
  204. GridLayout layout= new GridLayout();
  205. layout.numColumns= 2;
  206. layout.makeColumnsEqualWidth= true;
  207. layout.marginHeight= 0;
  208. layout.marginWidth= 0;
  209. composite.setLayout(layout);
  210. composite.setLayoutData(new GridData(GridData.FILL_BOTH));
  211. createTreeViewer(composite, width / 2, height);
  212. createListViewer(composite, width / 2, height);
  213. initialize();
  214. }
  215. /**
  216. * Creates this group's list viewer.
  217. * @param parent the parent composite
  218. * @param width the width
  219. * @param height the height
  220. */
  221. protected void createListViewer(Composite parent, int width, int height) {
  222. fListViewer= CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
  223. fListViewer.setUseHashlookup(true);
  224. GridData data= new GridData(GridData.FILL_BOTH);
  225. data.widthHint= width;
  226. data.heightHint= height;
  227. fListViewer.getTable().setLayoutData(data);
  228. fListViewer.setContentProvider(fListContentProvider);
  229. fListViewer.setLabelProvider(fListLabelProvider);
  230. fListViewer.addCheckStateListener(this);
  231. }
  232. /**
  233. * Creates this group's tree viewer.
  234. * @param parent parent composite
  235. * @param width the width
  236. * @param height the height
  237. */
  238. protected void createTreeViewer(Composite parent, int width, int height) {
  239. Tree tree= new Tree(parent, SWT.CHECK | SWT.BORDER);
  240. GridData data= new GridData(GridData.FILL_BOTH);
  241. data.widthHint= width;
  242. data.heightHint= height;
  243. tree.setLayoutData(data);
  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. /**
  253. * Returns a boolean indicating whether the passed tree element should be
  254. * at LEAST gray-checked. Note that this method does not consider whether
  255. * it should be white-checked, so a specified tree item which should be
  256. * white-checked will result in a <code>true</code> answer from this method.
  257. * To determine whether a tree item should be white-checked use method
  258. * #determineShouldBeWhiteChecked(Object).
  259. *
  260. * @param treeElement java.lang.Object
  261. * @return boolean
  262. * @see #determineShouldBeWhiteChecked(java.lang.Object)
  263. */
  264. protected boolean determineShouldBeAtLeastGrayChecked(Object treeElement) {
  265. // if any list items associated with treeElement are checked then it
  266. // retains its gray-checked status regardless of its children
  267. List<Object> checked= fCheckedStateStore.get(treeElement);
  268. if (checked != null && (!checked.isEmpty()))
  269. return true;
  270. // if any children of treeElement are still gray-checked then treeElement
  271. // must remain gray-checked as well
  272. Object[] children= getTreeChildren(treeElement);
  273. for (int i= 0; i < children.length; ++i) {
  274. if (fCheckedStateStore.containsKey(children[i]))
  275. return true;
  276. }
  277. return false;
  278. }
  279. /**
  280. * Returns a boolean indicating whether the passed tree item should be
  281. * white-checked.
  282. *
  283. * @return boolean
  284. * @param treeElement java.lang.Object
  285. */
  286. protected boolean determineShouldBeWhiteChecked(Object treeElement) {
  287. return areAllChildrenWhiteChecked(treeElement)
  288. && areAllElementsChecked(treeElement);
  289. }
  290. /**
  291. * Recursively adds appropriate tree elements to the collection of
  292. * known white-checked tree elements.
  293. *
  294. * @param treeElement java.lang.Object
  295. */
  296. protected void determineWhiteCheckedDescendents(Object treeElement) {
  297. // always go through all children first since their white-checked
  298. // statuses will be needed to determine the white-checked status for
  299. // this tree element
  300. Object[] children= getTreeChildren(treeElement);
  301. for (int i= 0; i < children.length; ++i)
  302. determineWhiteCheckedDescendents(children[i]);
  303. // now determine the white-checked status for this tree element
  304. if (determineShouldBeWhiteChecked(treeElement))
  305. setWhiteChecked(treeElement, true);
  306. }
  307. /**
  308. * Causes the tree viewer to expand all its items
  309. */
  310. public void expandAll() {
  311. fTreeViewer.expandAll();
  312. }
  313. /**
  314. * Answers a flat collection of all of the checked elements in the
  315. * list portion of self
  316. *
  317. * @return java.util.Vector
  318. */
  319. public Iterator<Object> getAllCheckedListItems() {
  320. Set<Object> result= new HashSet<Object>();
  321. Iterator<List<Object>> listCollectionsEnum= fCheckedStateStore.values().iterator();
  322. while (listCollectionsEnum.hasNext())
  323. result.addAll(listCollectionsEnum.next());
  324. return result.iterator();
  325. }
  326. /**
  327. * Answer a collection of all of the checked elements in the tree portion
  328. * of self
  329. *
  330. * @return java.util.Vector
  331. */
  332. public Set<Object> getAllCheckedTreeItems() {
  333. return new HashSet<Object>(fCheckedStateStore.keySet());
  334. }
  335. /**
  336. * Answers the number of elements that have been checked by the
  337. * user.
  338. *
  339. * @return int
  340. */
  341. public int getCheckedElementCount() {
  342. return fCheckedStateStore.size();
  343. }
  344. /**
  345. * Returns a count of the number of list items associated with a
  346. * given tree item.
  347. *
  348. * @return int
  349. * @param treeElement java.lang.Object
  350. */
  351. protected int getListItemsSize(Object treeElement) {
  352. Object[] elements= getListElements(treeElement);
  353. return elements.length;
  354. }
  355. /**
  356. * Gets the table that displays the folder content
  357. *
  358. * @return the table used to show the list
  359. */
  360. public Table getTable() {
  361. return fListViewer.getTable();
  362. }
  363. /**
  364. * Gets the tree that displays the list for a folder
  365. *
  366. * @return the tree used to show the folders
  367. */
  368. public Tree getTree() {
  369. return fTreeViewer.getTree();
  370. }
  371. /**
  372. * Adds the given filter to the tree viewer and
  373. * triggers refiltering and resorting of the elements.
  374. *
  375. * @param filter a viewer filter
  376. */
  377. public void addTreeFilter(ViewerFilter filter) {
  378. fTreeViewer.addFilter(filter);
  379. }
  380. /**
  381. * Adds the given filter to the list viewer and
  382. * triggers refiltering and resorting of the elements.
  383. *
  384. * @param filter a viewer filter
  385. */
  386. public void addListFilter(ViewerFilter filter) {
  387. fListViewer.addFilter(filter);
  388. }
  389. /**
  390. * Logically gray-check all ancestors of treeItem by ensuring that they
  391. * appear in the checked table
  392. * @param treeElement
  393. */
  394. protected void grayCheckHierarchy(Object treeElement) {
  395. // if this tree element is already gray then its ancestors all are as well
  396. if (fCheckedStateStore.containsKey(treeElement))
  397. return; // no need to proceed upwards from here
  398. fCheckedStateStore.put(treeElement, new ArrayList<Object>());
  399. if (determineShouldBeWhiteChecked(treeElement)) {
  400. setWhiteChecked(treeElement, true);
  401. }
  402. Object parent= fTreeContentProvider.getParent(treeElement);
  403. if (parent != null)
  404. grayCheckHierarchy(parent);
  405. }
  406. /**
  407. * Sets the initial checked state of the passed list element to true.
  408. * @param element
  409. */
  410. public void initialCheckListItem(Object element) {
  411. Object parent= fTreeContentProvider.getParent(element);
  412. fCurrentTreeSelection= parent;
  413. //As this is not done from the UI then set the box for updating from the selection to false
  414. listItemChecked(element, true, false);
  415. updateHierarchy(parent);
  416. }
  417. /**
  418. * Sets the initial checked state of the passed element to true,
  419. * as well as to all of its children and associated list elements
  420. * @param element
  421. */
  422. public void initialCheckTreeItem(Object element) {
  423. treeItemChecked(element, true);
  424. }
  425. /**
  426. * Initializes this group's viewers after they have been laid out.
  427. */
  428. protected void initialize() {
  429. fTreeViewer.setInput(fRoot);
  430. }
  431. /**
  432. * Callback that's invoked when the checked status of an item in the list
  433. * is changed by the user. Do not try and update the hierarchy if we are building the
  434. * initial list.
  435. * @param listElement
  436. * @param state
  437. * @param updatingFromSelection
  438. */
  439. protected void listItemChecked(
  440. Object listElement,
  441. boolean state,
  442. boolean updatingFromSelection) {
  443. List<Object> checkedListItems= fCheckedStateStore.get(fCurrentTreeSelection);
  444. if (state) {
  445. if (checkedListItems == null) {
  446. // since the associated tree item has gone from 0 -> 1 checked
  447. // list items, tree checking may need to be updated
  448. grayCheckHierarchy(fCurrentTreeSelection);
  449. checkedListItems= fCheckedStateStore.get(fCurrentTreeSelection);
  450. }
  451. checkedListItems.add(listElement);
  452. } else {
  453. checkedListItems.remove(listElement);
  454. if (checkedListItems.isEmpty()) {
  455. // since the associated tree item has gone from 1 -> 0 checked
  456. // list items, tree checking may need to be updated
  457. ungrayCheckHierarchy(fCurrentTreeSelection);
  458. }
  459. }
  460. if (updatingFromSelection)
  461. updateHierarchy(fCurrentTreeSelection);
  462. }
  463. /**
  464. * Notifies all checked state listeners that the passed element has had
  465. * its checked state changed to the passed state
  466. * @param event
  467. */
  468. protected void notifyCheckStateChangeListeners(CheckStateChangedEvent event) {
  469. Iterator<ICheckStateListener> listenersEnum= fListeners.iterator();
  470. while (listenersEnum.hasNext())
  471. listenersEnum.next().checkStateChanged(event);
  472. }
  473. /**
  474. *Sets the contents of the list viewer based upon the specified selected
  475. *tree element. This also includes checking the appropriate list items.
  476. *
  477. *@param treeElement java.lang.Object
  478. */
  479. protected void populateListViewer(final Object treeElement) {
  480. if (treeElement == fCurrentTreeSelection)
  481. return;
  482. fCurrentTreeSelection= treeElement;
  483. fListViewer.setInput(treeElement);
  484. List<Object> listItemsToCheck= fCheckedStateStore.get(treeElement);
  485. if (listItemsToCheck != null) {
  486. Iterator<Object> listItemsEnum= listItemsToCheck.iterator();
  487. while (listItemsEnum.hasNext())
  488. fListViewer.setChecked(listItemsEnum.next(), true);
  489. }
  490. }
  491. /**
  492. * Removes the passed listener from self's collection of clients
  493. * that listen for changes to element checked states
  494. *
  495. * @param listener ICheckStateListener
  496. */
  497. public void removeCheckStateListener(ICheckStateListener listener) {
  498. fListeners.remove(listener);
  499. }
  500. /**
  501. * Handles the selection of an item in the tree viewer
  502. *
  503. * @param event ISelection
  504. */
  505. public void selectionChanged(final SelectionChangedEvent event) {
  506. BusyIndicator.showWhile(getTable().getShell().getDisplay(), new Runnable() {
  507. public void run() {
  508. IStructuredSelection selection= (IStructuredSelection) event.getSelection();
  509. Object selectedElement= selection.getFirstElement();
  510. if (selectedElement == null) {
  511. fCurrentTreeSelection= null;
  512. fListViewer.setInput(fCurrentTreeSelection);
  513. return;
  514. }
  515. populateListViewer(selectedElement);
  516. }
  517. });
  518. }
  519. /**
  520. * Selects or deselect all of the elements in the tree depending on the value of the selection
  521. * boolean. Be sure to update the displayed files as well.
  522. * @param selection
  523. */
  524. public void setAllSelections(final boolean selection) {
  525. //Potentially long operation - show a busy cursor
  526. BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable() {
  527. public void run() {
  528. setTreeChecked(fRoot, selection);
  529. fListViewer.setAllChecked(selection);
  530. }
  531. });
  532. }
  533. /**
  534. * Sets the list viewer's providers to those passed
  535. *
  536. * @param contentProvider ITreeContentProvider
  537. * @param labelProvider ILabelProvider
  538. */
  539. public void setListProviders(
  540. IStructuredContentProvider contentProvider,
  541. ILabelProvider labelProvider) {
  542. fListViewer.setContentProvider(contentProvider);
  543. fListViewer.setLabelProvider(labelProvider);
  544. }
  545. /**
  546. * Sets the sorter that is to be applied to self's list viewer
  547. * @param comparator
  548. */
  549. public void setListComparator(ViewerComparator comparator) {
  550. fListViewer.setComparator(comparator);
  551. }
  552. /**
  553. * Sets the root of the widget to be new Root. Regenerate all of the tables and lists from this
  554. * value.
  555. *
  556. * @param newRoot
  557. */
  558. public void setRoot(Object newRoot) {
  559. this.fRoot= newRoot;
  560. initialize();
  561. }
  562. /**
  563. * Sets the checked state of the passed tree element appropriately, and
  564. * do so recursively to all of its child tree elements as well
  565. * @param treeElement
  566. * @param state
  567. */
  568. protected void setTreeChecked(Object treeElement, boolean state) {
  569. if (treeElement.equals(fCurrentTreeSelection)) {
  570. fListViewer.setAllChecked(state);
  571. }
  572. if (state) {
  573. Object[] listItems= getListElements(treeElement);
  574. List<Object> listItemsChecked= new ArrayList<Object>();
  575. for (int i= 0; i < listItems.length; ++i)
  576. listItemsChecked.add(listItems[i]);
  577. fCheckedStateStore.put(treeElement, listItemsChecked);
  578. } else
  579. fCheckedStateStore.remove(treeElement);
  580. setWhiteChecked(treeElement, state);
  581. fTreeViewer.setChecked(treeElement, state);
  582. fTreeViewer.setGrayed(treeElement, false);
  583. // now logically check/uncheck all children as well
  584. Object[] children= getTreeChildren(treeElement);
  585. for (int i= 0; i < children.length; ++i) {
  586. setTreeChecked(children[i], state);
  587. }
  588. }
  589. /**
  590. * Sets the tree viewer's providers to those passed
  591. *
  592. * @param contentProvider ITreeContentProvider
  593. * @param labelProvider ILabelProvider
  594. */
  595. public void setTreeProviders(
  596. ITreeContentProvider contentProvider,
  597. ILabelProvider labelProvider) {
  598. fTreeViewer.setContentProvider(contentProvider);
  599. fTreeViewer.setLabelProvider(labelProvider);
  600. }
  601. /**
  602. * Sets the sorter that is to be applied to self's tree viewer
  603. * @param sorter
  604. */
  605. public void setTreeComparator(ViewerComparator sorter) {
  606. fTreeViewer.setComparator(sorter);
  607. }
  608. /**
  609. * Adjusts the collection of references to white-checked tree elements appropriately.
  610. *
  611. * @param treeElement java.lang.Object
  612. * @param isWhiteChecked boolean
  613. */
  614. protected void setWhiteChecked(Object treeElement, boolean isWhiteChecked) {
  615. if (isWhiteChecked) {
  616. if (!fWhiteCheckedTreeItems.contains(treeElement))
  617. fWhiteCheckedTreeItems.add(treeElement);
  618. } else
  619. fWhiteCheckedTreeItems.remove(treeElement);
  620. }
  621. /**
  622. * Handle the collapsing of an element in a tree viewer
  623. * @param event
  624. */
  625. public void treeCollapsed(TreeExpansionEvent event) {
  626. // We don't need to do anything with this
  627. }
  628. /**
  629. * Handles the expansionsion of an element in a tree viewer
  630. * @param event
  631. */
  632. public void treeExpanded(TreeExpansionEvent event) {
  633. Object item= event.getElement();
  634. // First see if the children need to be given their checked state at all. If they've
  635. // already been realized then this won't be necessary
  636. if (!fExpandedTreeNodes.contains(item)) {
  637. fExpandedTreeNodes.add(item);
  638. checkNewTreeElements(getTreeChildren(item));
  639. }
  640. }
  641. /**
  642. * Callback that's invoked when the checked status of an item in the tree
  643. * is changed by the user.
  644. * @param treeElement
  645. * @param state
  646. */
  647. protected void treeItemChecked(Object treeElement, boolean state) {
  648. // recursively adjust all child tree elements appropriately
  649. setTreeChecked(treeElement, state);
  650. Object parent= fTreeContentProvider.getParent(treeElement);
  651. if (parent == null)
  652. return;
  653. // now update upwards in the tree hierarchy
  654. if (state)
  655. grayCheckHierarchy(parent);
  656. else
  657. ungrayCheckHierarchy(parent);
  658. updateHierarchy(treeElement);
  659. }
  660. /**
  661. * Logically un-gray-check all ancestors of treeItem iff appropriate.
  662. * @param treeElement
  663. */
  664. protected void ungrayCheckHierarchy(Object treeElement) {
  665. if (!determineShouldBeAtLeastGrayChecked(treeElement))
  666. fCheckedStateStore.remove(treeElement);
  667. Object parent= fTreeContentProvider.getParent(treeElement);
  668. if (parent != null)
  669. ungrayCheckHierarchy(parent);
  670. }
  671. /**
  672. * Sets the checked state of self and all ancestors appropriately
  673. * @param treeElement
  674. */
  675. protected void updateHierarchy(Object treeElement) {
  676. boolean whiteChecked= determineShouldBeWhiteChecked(treeElement);
  677. boolean shouldBeAtLeastGray= determineShouldBeAtLeastGrayChecked(treeElement);
  678. fTreeViewer.setChecked(treeElement, whiteChecked || shouldBeAtLeastGray);
  679. setWhiteChecked(treeElement, whiteChecked);
  680. if (whiteChecked)
  681. fTreeViewer.setGrayed(treeElement, false);
  682. else
  683. fTreeViewer.setGrayed(treeElement, shouldBeAtLeastGray);
  684. // proceed up the tree element hierarchy
  685. Object parent= fTreeContentProvider.getParent(treeElement);
  686. if (parent != null) {
  687. updateHierarchy(parent);
  688. }
  689. }
  690. /**
  691. * Update the selections of the tree elements in items to reflect the new
  692. * selections provided.
  693. *
  694. * @param items with keys of Object (the tree element) and values of List (the selected
  695. * list elements).
  696. */
  697. public void updateSelections(final Map<Object, List<Object>> items) {
  698. //Potentially long operation - show a busy cursor
  699. BusyIndicator.showWhile(fTreeViewer.getControl().getDisplay(), new Runnable() {
  700. public void run() {
  701. handleUpdateSelection(items);
  702. }
  703. });
  704. }
  705. /**
  706. * Returns the result of running the given elements through the filters.
  707. * @param filters
  708. *
  709. * @param elements the elements to filter
  710. * @return only the elements which all filters accept
  711. */
  712. protected Object[] filter(ViewerFilter[] filters, Object[] elements) {
  713. if (filters != null) {
  714. ArrayList<Object> filtered = new ArrayList<Object>(elements.length);
  715. for (int i = 0; i < elements.length; i++) {
  716. boolean add = true;
  717. for (int j = 0; j < filters.length; j++) {
  718. add = filters[j].select(null, null, elements[i]);
  719. if (!add)
  720. break;
  721. }
  722. if (add)
  723. filtered.add(elements[i]);
  724. }
  725. return filtered.toArray();
  726. }
  727. return elements;
  728. }
  729. private Object[] getTreeChildren(Object element) {
  730. return filter(fTreeViewer.getFilters(), fTreeContentProvider.getChildren(element));
  731. }
  732. private Object[] getListElements(Object element) {
  733. return filter(fListViewer.getFilters(), fListContentProvider.getElements(element));
  734. }
  735. public Set<Object> getWhiteCheckedTreeItems() {
  736. return new HashSet<Object>(fWhiteCheckedTreeItems);
  737. }
  738. private void handleUpdateSelection(Map<Object, List<Object>> items) {
  739. Iterator<Object> keyIterator= items.keySet().iterator();
  740. //Update the store before the hierarchy to prevent updating parents before all of the children are done
  741. while (keyIterator.hasNext()) {
  742. Object key= keyIterator.next();
  743. //Replace the items in the checked state store with those from the supplied items
  744. List<Object> selections= items.get(key);
  745. if (selections.size() == 0)
  746. //If it is empty remove it from the list
  747. fCheckedStateStore.remove(key);
  748. else {
  749. fCheckedStateStore.put(key, selections);
  750. // proceed up the tree element hierarchy
  751. Object parent= fTreeContentProvider.getParent(key);
  752. if (parent != null) {
  753. addToHierarchyToCheckedStore(parent);
  754. }
  755. }
  756. }
  757. //Now update hierarchies
  758. keyIterator= items.keySet().iterator();
  759. while (keyIterator.hasNext()) {
  760. Object key= keyIterator.next();
  761. updateHierarchy(key);
  762. if (fCurrentTreeSelection != null && fCurrentTreeSelection.equals(key)) {
  763. fListViewer.setAllChecked(false);
  764. fListViewer.setCheckedElements(items.get(key).toArray());
  765. }
  766. }
  767. }
  768. /**
  769. * Checks if an element is grey checked.
  770. * @param object
  771. * @return if an element is grey checked.
  772. */
  773. public boolean isTreeItemGreyChecked(Object object) {
  774. return fTreeViewer.getGrayed(object);
  775. }
  776. /**
  777. * For a given element, expand its chidren to a level.
  778. * @param object
  779. * @param level
  780. */
  781. public void expandTreeToLevel(Object object, int level) {
  782. fTreeViewer.expandToLevel(object, level);
  783. }
  784. /**
  785. * @param selection
  786. */
  787. public void setTreeSelection(ISelection selection) {
  788. fTreeViewer.setSelection(selection);
  789. }
  790. }