protected void ShowLocations(IList <FileLocationInfo> locations, FileLocationInfo currentLocation, string caption, bool bindToPsi)
        {
            var lifetimeDefinition = Lifetimes.Define(lifetime);

            if (!Enumerable.Any(locations))
            {
                agent.ShowBalloon(lifetimeDefinition.Lifetime, caption,
                                  string.Format("There are no {0}.", caption.ToLowerInvariant()), null,
                                  new[] { "OK" }, false, balloonLifetime =>
                {
                    agent.ButtonClicked.Advise(balloonLifetime, _ => lifetimeDefinition.Terminate());
                });
                return;
            }

            var options = new List <BalloonOption>();

            foreach (var locationInfo in locations.Distinct().Where(l => l.ProjectFile.IsValid() || l.FileSystemPath != null))
            {
                var descriptor = new SimpleMenuItem();

                var occurence = GetOccurence(locationInfo, bindToPsi);
                if (occurence != null)
                {
                    presentationManager.DescribeOccurence(descriptor, occurence, null);
                    var enabled = locationInfo != currentLocation;
                    options.Add(new BalloonOption(descriptor.Text + string.Format(" ({0})", descriptor.ShortcutText), false, enabled, locationInfo));
                }
            }

            agent.ShowBalloon(lifetimeDefinition.Lifetime, caption, string.Empty, options, new[] { "Done" }, true,
                              balloonLifetime =>
            {
                agent.BalloonOptionClicked.Advise(balloonLifetime, o =>
                {
                    lifetimeDefinition.Terminate();

                    var locationInfo = o as FileLocationInfo;
                    if (locationInfo == null)
                    {
                        return;
                    }

                    shellLocks.ExecuteOrQueueReadLock("GotoRecentFiles", () =>
                    {
                        using (ReadLockCookie.Create())
                        {
                            PsiFiles.CommitAllDocuments();
                            var occurence = GetOccurence(locationInfo, bindToPsi);
                            if (occurence != null)
                            {
                                occurence.Navigate(solution, popupWindowContext.Source, true);
                            }
                        }
                    });
                });

                agent.ButtonClicked.Advise(balloonLifetime, _ => lifetimeDefinition.Terminate());
            });
        }
        private static IOccurence GetOccurence(FileLocationInfo location, bool bindToPsi)
        {
            var projectFile = location.ProjectFile;

            if (bindToPsi)
            {
                var sourceFile = projectFile.ToSourceFile();
                if (sourceFile != null)
                {
                    DeclaredElementEnvoy <INamespace>   boundNamespace;
                    DeclaredElementEnvoy <ITypeElement> boundTypeElement;
                    DeclaredElementEnvoy <ITypeMember>  boundTypeMember;
                    TextControlToPsi.BindToPsi(sourceFile, new TextRange(location.CaretOffset), out boundTypeMember, out boundTypeElement, out boundNamespace);
                    if (boundTypeMember != null || boundTypeElement != null)
                    {
                        var declaredElement = ((IDeclaredElementEnvoy)boundTypeMember ?? boundTypeElement).GetValidDeclaredElement();
                        if (declaredElement != null)
                        {
                            return(new CustomRangeOccurence(sourceFile, new DocumentRange(sourceFile.Document, new TextRange(location.CaretOffset)), new OccurencePresentationOptions {
                                ContainerStyle = ContainerDisplayStyle.File
                            }));
                        }
                    }
                }
            }

            //project file can loose its owner project (i.e. micsFilesProject) during provision tab navigation
            if (projectFile.GetProject() == null)
            {
                return(new DecompiledFileOccurence(location.FileSystemPath, new TextRange(location.CaretOffset), location.CachedPresentation, projectFile.GetSolution()));
            }

            if (projectFile.IsValid())
            {
                return(new ProjectItemOccurence(projectFile, new OccurencePresentationOptions {
                    ContainerStyle = ContainerDisplayStyle.NoContainer
                }));
            }

            return(null);
        }