|
Lines 10-28
Link Here
|
| 10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
| 11 |
package org.eclipse.ui.internal.navigator; |
11 |
package org.eclipse.ui.internal.navigator; |
| 12 |
|
12 |
|
| 13 |
import java.util.Arrays; |
13 |
import java.util.*; |
| 14 |
import java.util.HashSet; |
|
|
| 15 |
import java.util.Iterator; |
| 16 |
import java.util.Set; |
| 17 |
|
14 |
|
| 18 |
import org.eclipse.jface.viewers.ITreeContentProvider; |
15 |
import org.eclipse.jface.viewers.*; |
| 19 |
import org.eclipse.jface.viewers.Viewer; |
|
|
| 20 |
import org.eclipse.osgi.util.NLS; |
16 |
import org.eclipse.osgi.util.NLS; |
| 21 |
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentExtension; |
17 |
import org.eclipse.ui.internal.navigator.extensions.NavigatorContentExtension; |
| 22 |
import org.eclipse.ui.internal.navigator.extensions.OverridePolicy; |
18 |
import org.eclipse.ui.internal.navigator.extensions.OverridePolicy; |
| 23 |
import org.eclipse.ui.navigator.CommonViewer; |
19 |
import org.eclipse.ui.navigator.*; |
| 24 |
import org.eclipse.ui.navigator.INavigatorContentDescriptor; |
|
|
| 25 |
import org.eclipse.ui.navigator.IPipelinedTreeContentProvider; |
| 26 |
|
20 |
|
| 27 |
/** |
21 |
/** |
| 28 |
* <p> |
22 |
* <p> |
|
Lines 54-60
Link Here
|
| 54 |
* |
48 |
* |
| 55 |
*/ |
49 |
*/ |
| 56 |
public class NavigatorContentServiceContentProvider implements |
50 |
public class NavigatorContentServiceContentProvider implements |
| 57 |
ITreeContentProvider { |
51 |
ITreeContentProvider, ITreePathContentProvider { |
| 58 |
|
52 |
|
| 59 |
private static final Object[] NO_CHILDREN = new Object[0]; |
53 |
private static final Object[] NO_CHILDREN = new Object[0]; |
| 60 |
|
54 |
|
|
Lines 62-67
Link Here
|
| 62 |
|
56 |
|
| 63 |
private final boolean isContentServiceSelfManaged; |
57 |
private final boolean isContentServiceSelfManaged; |
| 64 |
|
58 |
|
|
|
59 |
private Viewer viewer; |
| 60 |
|
| 65 |
/** |
61 |
/** |
| 66 |
* <p> |
62 |
* <p> |
| 67 |
* Creates a cached {@link NavigatorContentService} from the given |
63 |
* Creates a cached {@link NavigatorContentService} from the given |
|
Lines 210-215
Link Here
|
| 210 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) |
206 |
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) |
| 211 |
*/ |
207 |
*/ |
| 212 |
public synchronized Object[] getChildren(Object aParentElement) { |
208 |
public synchronized Object[] getChildren(Object aParentElement) { |
|
|
209 |
return internalGetChildren(aParentElement); |
| 210 |
} |
| 211 |
|
| 212 |
private Object[] internalGetChildren(Object aParentElementOrPath) { |
| 213 |
Object aParentElement = internalAsElement(aParentElementOrPath); |
| 213 |
Set enabledExtensions = contentService |
214 |
Set enabledExtensions = contentService |
| 214 |
.findContentExtensionsByTriggerPoint(aParentElement); |
215 |
.findContentExtensionsByTriggerPoint(aParentElement); |
| 215 |
if (enabledExtensions.size() == 0) |
216 |
if (enabledExtensions.size() == 0) |
|
Lines 227-238
Link Here
|
| 227 |
enabledExtensions)) { |
228 |
enabledExtensions)) { |
| 228 |
|
229 |
|
| 229 |
contributedChildren = foundExtension.internalGetContentProvider() |
230 |
contributedChildren = foundExtension.internalGetContentProvider() |
| 230 |
.getChildren(aParentElement); |
231 |
.getChildren(aParentElementOrPath); |
| 231 |
|
232 |
|
| 232 |
overridingExtensions = foundExtension |
233 |
overridingExtensions = foundExtension |
| 233 |
.getOverridingExtensionsForTriggerPoint(aParentElement); |
234 |
.getOverridingExtensionsForTriggerPoint(aParentElement); |
| 234 |
|
235 |
|
| 235 |
if (overridingExtensions.length > 0) { |
236 |
if (overridingExtensions.length > 0) { |
|
|
237 |
// TODO: could pass tree path through pipeline |
| 236 |
contributedChildren = pipelineChildren(aParentElement, |
238 |
contributedChildren = pipelineChildren(aParentElement, |
| 237 |
overridingExtensions, |
239 |
overridingExtensions, |
| 238 |
new HashSet(Arrays.asList(contributedChildren))) |
240 |
new HashSet(Arrays.asList(contributedChildren))) |
|
Lines 274-280
Link Here
|
| 274 |
* Query each of <code>theOverridingExtensions</code> for children, and |
276 |
* Query each of <code>theOverridingExtensions</code> for children, and |
| 275 |
* then pipe them through the Pipeline content provider. |
277 |
* then pipe them through the Pipeline content provider. |
| 276 |
* |
278 |
* |
| 277 |
* @param aParent |
279 |
* @param aParentOrPath |
| 278 |
* The parent element in the tree |
280 |
* The parent element in the tree |
| 279 |
* @param theOverridingExtensions |
281 |
* @param theOverridingExtensions |
| 280 |
* The set of overriding extensions that should participate in |
282 |
* The set of overriding extensions that should participate in |
|
Lines 284-290
Link Here
|
| 284 |
* modifiable) |
286 |
* modifiable) |
| 285 |
* @return The set of children to return to the viewer |
287 |
* @return The set of children to return to the viewer |
| 286 |
*/ |
288 |
*/ |
| 287 |
private Set pipelineChildren(Object aParent, |
289 |
private Set pipelineChildren(Object aParentOrPath, |
| 288 |
NavigatorContentExtension[] theOverridingExtensions, |
290 |
NavigatorContentExtension[] theOverridingExtensions, |
| 289 |
Set theCurrentChildren) { |
291 |
Set theCurrentChildren) { |
| 290 |
IPipelinedTreeContentProvider pipelinedContentProvider; |
292 |
IPipelinedTreeContentProvider pipelinedContentProvider; |
|
Lines 295-306
Link Here
|
| 295 |
if (theOverridingExtensions[i].getContentProvider() instanceof IPipelinedTreeContentProvider) { |
297 |
if (theOverridingExtensions[i].getContentProvider() instanceof IPipelinedTreeContentProvider) { |
| 296 |
pipelinedContentProvider = (IPipelinedTreeContentProvider) theOverridingExtensions[i] |
298 |
pipelinedContentProvider = (IPipelinedTreeContentProvider) theOverridingExtensions[i] |
| 297 |
.getContentProvider(); |
299 |
.getContentProvider(); |
| 298 |
pipelinedContentProvider.getPipelinedChildren(aParent, |
300 |
pipelinedContentProvider.getPipelinedChildren(aParentOrPath, |
| 299 |
pipelinedChildren); |
301 |
pipelinedChildren); |
| 300 |
overridingExtensions = theOverridingExtensions[i] |
302 |
overridingExtensions = theOverridingExtensions[i] |
| 301 |
.getOverridingExtensionsForTriggerPoint(aParent); |
303 |
.getOverridingExtensionsForTriggerPoint(aParentOrPath); |
| 302 |
if (overridingExtensions.length > 0) |
304 |
if (overridingExtensions.length > 0) |
| 303 |
pipelinedChildren = pipelineChildren(aParent, |
305 |
pipelinedChildren = pipelineChildren(aParentOrPath, |
| 304 |
overridingExtensions, pipelinedChildren); |
306 |
overridingExtensions, pipelinedChildren); |
| 305 |
} |
307 |
} |
| 306 |
} |
308 |
} |
|
Lines 564-570
Link Here
|
| 564 |
*/ |
566 |
*/ |
| 565 |
public synchronized void inputChanged(Viewer aViewer, Object anOldInput, |
567 |
public synchronized void inputChanged(Viewer aViewer, Object anOldInput, |
| 566 |
Object aNewInput) { |
568 |
Object aNewInput) { |
|
|
569 |
viewer = aViewer; |
| 567 |
contentService.updateService(aViewer, anOldInput, aNewInput); |
570 |
contentService.updateService(aViewer, anOldInput, aNewInput); |
| 568 |
} |
571 |
} |
| 569 |
|
572 |
|
|
|
573 |
/* (non-Javadoc) |
| 574 |
* @see org.eclipse.jface.viewers.ITreePathContentProvider#getChildren(org.eclipse.jface.viewers.TreePath) |
| 575 |
*/ |
| 576 |
public Object[] getChildren(TreePath parentPath) { |
| 577 |
return internalGetChildren(parentPath); |
| 578 |
} |
| 579 |
|
| 580 |
/* (non-Javadoc) |
| 581 |
* @see org.eclipse.jface.viewers.ITreePathContentProvider#hasChildren(org.eclipse.jface.viewers.TreePath) |
| 582 |
*/ |
| 583 |
public boolean hasChildren(TreePath path) { |
| 584 |
Object anElement = internalAsElement(path); |
| 585 |
Set resultInstances = contentService |
| 586 |
.findContentExtensionsByTriggerPoint(anElement); |
| 587 |
|
| 588 |
NavigatorContentExtension ext; |
| 589 |
for (Iterator itr = resultInstances.iterator(); itr.hasNext();) { |
| 590 |
ext = (NavigatorContentExtension) itr.next(); |
| 591 |
if (!ext.isLoaded()) |
| 592 |
return true; |
| 593 |
ITreeContentProvider cp = ext.internalGetContentProvider(); |
| 594 |
if (cp instanceof ITreePathContentProvider) { |
| 595 |
ITreePathContentProvider tpcp = (ITreePathContentProvider) cp; |
| 596 |
if (tpcp.hasChildren(path)) { |
| 597 |
return true; |
| 598 |
} |
| 599 |
} else if (cp.hasChildren(anElement)) |
| 600 |
return true; |
| 601 |
} |
| 602 |
|
| 603 |
return false; |
| 604 |
} |
| 605 |
|
| 606 |
/* (non-Javadoc) |
| 607 |
* @see org.eclipse.jface.viewers.ITreePathContentProvider#getParents(java.lang.Object) |
| 608 |
*/ |
| 609 |
public TreePath[] getParents(Object anElement) { |
| 610 |
Set extensions = contentService |
| 611 |
.findContentExtensionsWithPossibleChild(anElement); |
| 612 |
|
| 613 |
Set result = new HashSet(); |
| 614 |
NavigatorContentExtension foundExtension; |
| 615 |
NavigatorContentExtension[] overridingExtensions; |
| 616 |
for (Iterator itr = extensions.iterator(); itr.hasNext();) { |
| 617 |
foundExtension = (NavigatorContentExtension) itr.next(); |
| 618 |
try { |
| 619 |
|
| 620 |
if (!shouldDeferToOverridePath(foundExtension.getDescriptor(), |
| 621 |
extensions)) { |
| 622 |
|
| 623 |
// We know the content provider is a SafeDelegateTreeContentProvider |
| 624 |
// which implements ITreePathContentProvider |
| 625 |
ITreeContentProvider tcp = foundExtension.internalGetContentProvider(); |
| 626 |
if (tcp instanceof ITreePathContentProvider) { |
| 627 |
ITreePathContentProvider tpcp = (ITreePathContentProvider) tcp; |
| 628 |
TreePath[] parents = tpcp.getParents(anElement); |
| 629 |
Set parentPaths = asSet(parents); |
| 630 |
overridingExtensions = foundExtension |
| 631 |
.getOverridingExtensionsForPossibleChild(anElement); |
| 632 |
if (overridingExtensions.length > 0) { |
| 633 |
parentPaths = pipelineParents(anElement, |
| 634 |
overridingExtensions, parentPaths); |
| 635 |
} |
| 636 |
result.addAll(parentPaths); |
| 637 |
} |
| 638 |
} |
| 639 |
} catch (RuntimeException re) { |
| 640 |
NavigatorPlugin |
| 641 |
.logError( |
| 642 |
0, |
| 643 |
NLS |
| 644 |
.bind( |
| 645 |
CommonNavigatorMessages.Could_not_provide_children_for_element, |
| 646 |
new Object[] { foundExtension |
| 647 |
.getDescriptor() |
| 648 |
.getId() }), re); |
| 649 |
} catch (Error e) { |
| 650 |
NavigatorPlugin |
| 651 |
.logError( |
| 652 |
0, |
| 653 |
NLS |
| 654 |
.bind( |
| 655 |
CommonNavigatorMessages.Could_not_provide_children_for_element, |
| 656 |
new Object[] { foundExtension |
| 657 |
.getDescriptor() |
| 658 |
.getId() }), e); |
| 659 |
|
| 660 |
} |
| 661 |
} |
| 662 |
|
| 663 |
return (TreePath[]) result.toArray(new TreePath[result.size()]); |
| 664 |
} |
| 665 |
|
| 666 |
/** |
| 667 |
* Return the objects as a set. |
| 668 |
* @param objects the objects |
| 669 |
* @return a set that contains the objects |
| 670 |
*/ |
| 671 |
private Set asSet(Object[] objects) { |
| 672 |
Set parentPaths = new HashSet(); |
| 673 |
parentPaths.addAll(Arrays.asList(objects)); |
| 674 |
return parentPaths; |
| 675 |
} |
| 676 |
|
| 677 |
/** |
| 678 |
* Query each of <code>theOverridingExtensions</code> for in order |
| 679 |
* to adjust the parent paths of the contributor of the element. |
| 680 |
* |
| 681 |
* TODO: This method would be cleaner if TreePaths were added to the pipeline API. |
| 682 |
* |
| 683 |
* @param anInputElement |
| 684 |
* The input element in the tree |
| 685 |
* @param theOverridingExtensions |
| 686 |
* The set of overriding extensions that should participate in |
| 687 |
* the pipeline chain |
| 688 |
* @param theParentPaths |
| 689 |
* The current elements to return to the viewer (should be |
| 690 |
* modifiable) |
| 691 |
* @return The set of elements to return to the viewer |
| 692 |
*/ |
| 693 |
private Set pipelineParents(Object anInputElement, |
| 694 |
NavigatorContentExtension[] theOverridingExtensions, |
| 695 |
Set theParentPaths) { |
| 696 |
IPipelinedTreeContentProvider pipelinedContentProvider; |
| 697 |
NavigatorContentExtension[] overridingExtensions; |
| 698 |
for (int i = 0; i < theOverridingExtensions.length; i++) { |
| 699 |
|
| 700 |
if (theOverridingExtensions[i].getContentProvider() instanceof IPipelinedTreeContentProvider) { |
| 701 |
pipelinedContentProvider = (IPipelinedTreeContentProvider) theOverridingExtensions[i] |
| 702 |
.getContentProvider(); |
| 703 |
|
| 704 |
Set adjustedParentPaths = new HashSet(); |
| 705 |
if (theParentPaths.isEmpty()) { |
| 706 |
// Need to handle the case where the content provider doesn't |
| 707 |
// known the parent but the pipeline does |
| 708 |
Object aSuggestedParent = pipelinedContentProvider.getPipelinedParent( |
| 709 |
anInputElement, null); |
| 710 |
if (aSuggestedParent != null) { |
| 711 |
Collection newPaths = getPathsForElement(pipelinedContentProvider, aSuggestedParent); |
| 712 |
adjustedParentPaths.add(newPaths); |
| 713 |
} |
| 714 |
} else { |
| 715 |
Set pipedParents = new HashSet(); |
| 716 |
for (Iterator iter = theParentPaths.iterator(); iter.hasNext();) { |
| 717 |
TreePath parentPath = (TreePath) iter.next(); |
| 718 |
Object parentElement = internalAsElement(parentPath); |
| 719 |
|
| 720 |
// We only want to pipe a parent once even if it is the tail of multiple paths |
| 721 |
if (!pipedParents.contains(parentElement)) { |
| 722 |
pipedParents.add(parentElement); |
| 723 |
// Push the parent through the pipeline |
| 724 |
Object aSuggestedParent = pipelinedContentProvider.getPipelinedParent( |
| 725 |
anInputElement, parentElement); |
| 726 |
// If the parent was modified, get the new path |
| 727 |
if (aSuggestedParent != parentElement) { |
| 728 |
Collection newPaths = getPathsForElement(pipelinedContentProvider, aSuggestedParent); |
| 729 |
adjustedParentPaths.add(newPaths); |
| 730 |
} else { |
| 731 |
adjustedParentPaths.add(parentPath); |
| 732 |
} |
| 733 |
} |
| 734 |
} |
| 735 |
} |
| 736 |
overridingExtensions = theOverridingExtensions[i] |
| 737 |
.getOverridingExtensionsForTriggerPoint(anInputElement); |
| 738 |
if (overridingExtensions.length > 0) |
| 739 |
adjustedParentPaths = pipelineParents(anInputElement, |
| 740 |
overridingExtensions, adjustedParentPaths); |
| 741 |
theParentPaths = adjustedParentPaths; |
| 742 |
} |
| 743 |
} |
| 744 |
return theParentPaths; |
| 745 |
} |
| 746 |
|
| 747 |
/** |
| 748 |
* Return all the potential paths for the given element from the given |
| 749 |
* content provider. This is done by getting the parent paths of |
| 750 |
* the element and then appending he element to these paths. |
| 751 |
* @param aContentProvider the content povider |
| 752 |
* @param anElement the element |
| 753 |
* @return the tree path fo the given element |
| 754 |
*/ |
| 755 |
private Collection getPathsForElement(ITreeContentProvider aContentProvider, Object anElement) { |
| 756 |
List result = new ArrayList(); |
| 757 |
if (aContentProvider instanceof ITreePathContentProvider) { |
| 758 |
ITreePathContentProvider tpcp = (ITreePathContentProvider) aContentProvider; |
| 759 |
TreePath[] paths = tpcp.getParents(anElement); |
| 760 |
for (int i = 0; i < paths.length; i++) { |
| 761 |
TreePath path = paths[i]; |
| 762 |
result.add(path.createChildPath(anElement)); |
| 763 |
} |
| 764 |
} else { |
| 765 |
// We should never get here since SafeDelegateTreeContentProvider is an ITreePathContentProvider |
| 766 |
result.add(TreePath.EMPTY.createChildPath(anElement)); |
| 767 |
} |
| 768 |
return result; |
| 769 |
} |
| 770 |
|
| 771 |
/** |
| 772 |
* Get the element from an element or tree path argument. |
| 773 |
* @param parentElementOrPath the element or tree path |
| 774 |
* @return the element |
| 775 |
*/ |
| 776 |
private Object internalAsElement(Object parentElementOrPath) { |
| 777 |
if (parentElementOrPath instanceof TreePath) { |
| 778 |
TreePath tp = (TreePath) parentElementOrPath; |
| 779 |
if (tp.getSegmentCount() > 0) { |
| 780 |
return tp.getLastSegment(); |
| 781 |
} |
| 782 |
// If the path is empty, the parent element is the root |
| 783 |
return viewer.getInput(); |
| 784 |
} |
| 785 |
return parentElementOrPath; |
| 786 |
} |
| 787 |
|
| 570 |
} |
788 |
} |