/// <summary>
        /// Show the statement completion popup with the list of items.
        /// </summary>
        public void ShowStatementCompletionForm(IList <ListViewItem> items)
        {
            if (items.Count == 0)
            {
                HideStatementCompletionForm();
                return;
            }
            bool show = false;

            if (StatementCompletionForm == null)
            {
                StatementCompletionForm = new StatementCompletionForm {
                    TextBox = TextBox
                };
                StatementCompletionForm.ListView.MouseDown     += ListView_MouseDown;
                StatementCompletionForm.ListView.SmallImageList = _imageList;
                show = true;
            }
            StatementCompletionForm.SetListItems(items);
            StatementCompletionForm.ResizeToIdealSize(ScreenRect);
            if (show)
            {
                StatementCompletionForm.Show(TextBox);
            }
        }
 public void HideStatementCompletionForm()
 {
     if (StatementCompletionForm != null)
     {
         StatementCompletionForm.Close();
         StatementCompletionForm = null;
     }
 }
 protected void TextBox_GotFocus(object sender, EventArgs e)
 {
     if (StatementCompletionForm != null && !StatementCompletionForm.Visible)
     {
         StatementCompletionForm.Show();
         StatementCompletionForm.ResizeToIdealSize(ScreenRect);
     }
     else
     {
         DoStatementCompletion();
     }
 }
 void HideStatementCompletionFormIfLostFocus()
 {
     if (TextBox == null || TextBox.Focused)
     {
         return;
     }
     if (StatementCompletionForm != null)
     {
         if (StatementCompletionForm.Focused || StatementCompletionForm.ListView.Focused)
         {
             return;
         }
         StatementCompletionForm.Hide();
     }
     if (TextBoxLoseFocus != null)
     {
         TextBoxLoseFocus.Invoke();
     }
 }
        [MethodImpl(MethodImplOptions.NoOptimization)] // TODO(nicksh): reenable optimizations after we track down a NullReferenceException
        public static IList <ListViewItem> CreateListViewItems(IList <ProteinMatch> matches, String searchText, ProteinMatchTypes matchTypes, PeptideSettings peptideSettings, int maxCount)
        {
            var listItems      = new SortedList <string, ListViewItem>();
            var setUsedMatches = new HashSet <string>();

            // First check for matching by sequence
            foreach (var match in matches)
            {
                if (matchTypes.Contains(ProteinMatchType.sequence))
                {
                    HashSet <String> addedPeptideSequences = new HashSet <string>();
                    FastaSequence    fastaSequence;
                    try
                    {
                        fastaSequence = new FastaSequence("name", "description", new ProteinMetadata[0], match.Protein.Sequence); // Not L10N
                    }
                    catch (InvalidDataException)
                    {
                        // It's possible that the peptide sequence in the fasta file was bogus, in which case we just don't digest it.
                        continue;
                    }
                    foreach (Peptide peptide in peptideSettings.Enzyme.Digest(fastaSequence, peptideSettings.DigestSettings))
                    {
                        if (!peptide.Sequence.StartsWith(searchText))
                        {
                            continue;
                        }
                        if (!addedPeptideSequences.Add(peptide.Sequence))
                        {
                            continue;
                        }
                        var listItem = new ListViewItem
                        {
                            Text = peptide.Sequence,
                            Tag  = new StatementCompletionItem
                            {
                                Peptide     = peptide.Sequence,
                                ProteinInfo = match.Protein.ProteinMetadata,
                                SearchText  = searchText
                            },
                        };
                        StatementCompletionForm.AddDescription(listItem,
                                                               match.Protein.ProteinMetadata.TextForMatchTypes(matchTypes),
                                                               null);
                        setUsedMatches.Add(match.Protein.Name);
                        listItem.ImageIndex = (int)ImageId.peptide;
                        var tooltip = new StringBuilder();
                        tooltip.AppendLine(Resources.StatementCompletionTextBox_CreateListViewItems_Descriptions)
                        .Append(match.Protein.ProteinMetadata.TextForMatchTypes(matchTypes));
                        foreach (var name in match.Protein.AlternativeNames)
                        {
                            tooltip.AppendLine().Append(name.TextForMatchTypes(matchTypes));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                        // Note the leading space in this sort key - we'd like to list sequence matches first
                        var key = TextUtil.SpaceSeparate(" ", listItem.Text, listItem.ToolTipText); // Not L10N
                        if (!listItems.ContainsKey(key))
                        {
                            listItems.Add(key, listItem);
                        }
                    }
                }
            }
            if (listItems.Count >= maxCount)
            {
                return(new List <ListViewItem>(listItems.Values));  // We used to exit here if we had any matches - but that's frustrating when you're not actually trying to match by sequence
            }

            // Decide which field not to display on righthand side, based on what's already showing on the left due to View|Targets|By* menu
            ProteinMatchTypes displayMatchTypes = ProteinMatchTypes.ALL;

            switch (SequenceTree.ProteinsDisplayMode)
            {
            case ProteinMetadataManager.ProteinDisplayMode.ByName:
                displayMatchTypes = displayMatchTypes.Except(ProteinMatchType.name);
                break;

            case ProteinMetadataManager.ProteinDisplayMode.ByAccession:
                displayMatchTypes = displayMatchTypes.Except(ProteinMatchType.accession);
                break;

            case ProteinMetadataManager.ProteinDisplayMode.ByGene:
                displayMatchTypes = displayMatchTypes.Except(ProteinMatchType.gene);
                break;

            case ProteinMetadataManager.ProteinDisplayMode.ByPreferredName:
                displayMatchTypes = displayMatchTypes.Except(ProteinMatchType.preferredName);
                break;
            }

            ProteinMatchTypes secondPassMatchTypes = matchTypes.Except(
                ProteinMatchType.sequence,     // We already did sequence
                ProteinMatchType.description); // And aren't ready for description

            foreach (var match in matches)
            {
                if (setUsedMatches.Contains(match.Protein.Name))
                {
                    continue;
                }
                // Try matching on name, accession etc - cycle through name, accession, preferredName, gene
                foreach (ProteinMatchType tryType in secondPassMatchTypes)
                {
                    if (match.MatchTypes.Contains(tryType))
                    {
                        var listItem = new ListViewItem();
                        // Show description, and any other fields we were searching on
                        if (match.AlternativeName != null)
                        {
                            listItem.Text = ProteinMetadataManager.ProteinModalDisplayText(match.AlternativeName, Settings.Default.ShowPeptidesDisplayMode);
                            listItem.Tag  = new StatementCompletionItem {
                                ProteinInfo = match.AlternativeName, SearchText = searchText
                            };
                            StatementCompletionForm.AddDescription(listItem,
                                                                   match.AlternativeName.TextForMatchTypes(displayMatchTypes.Except(ProteinMatchType.name)), searchText);
                        }
                        else
                        {
                            listItem.Text = ProteinMetadataManager.ProteinModalDisplayText(match.Protein.ProteinMetadata, Settings.Default.ShowPeptidesDisplayMode);
                            listItem.Tag  = new StatementCompletionItem {
                                ProteinInfo = match.Protein.ProteinMetadata, SearchText = searchText
                            };
                            StatementCompletionForm.AddDescription(listItem,
                                                                   match.Protein.ProteinMetadata.TextForMatchTypes(displayMatchTypes), searchText);
                        }
                        setUsedMatches.Add(match.Protein.Name);
                        listItem.ImageIndex = (int)ImageId.protein;
                        var tooltip = new StringBuilder();
                        tooltip.AppendLine(Resources.StatementCompletionTextBox_CreateListViewItems_Descriptions)
                        .Append(match.Protein.ProteinMetadata.TextForMatchTypes(displayMatchTypes));
                        foreach (var altName in match.Protein.AlternativeNames)
                        {
                            tooltip.AppendLine().Append(altName.TextForMatchTypes(displayMatchTypes));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                        // We want the sort to be on the particular bit of metadata that we matched
                        var key = TextUtil.SpaceSeparate(match.Protein.ProteinMetadata.TextForMatchTypes(ProteinMatchTypes.Singleton(tryType)),
                                                         listItem.Text, listItem.ToolTipText);
                        if (!listItems.ContainsKey(key))
                        {
                            listItems.Add(key, listItem);
                        }
                        break;
                    }
                }
            }
            if (listItems.Count >= maxCount)
            {
                return(new List <ListViewItem>(listItems.Values));  // We used to exit here if we had any matches - but that's frustrating when you're not actually trying to match by sequence
            }

            // Any matches by description?
            foreach (var match in matches)
            {
                if (setUsedMatches.Contains(match.Protein.Name))
                {
                    continue;
                }
                if (match.MatchTypes.Contains(ProteinMatchType.description))
                {
                    ProteinMetadata mainName    = match.AlternativeDescription;
                    string          matchName   = match.Protein.Name;
                    var             proteinInfo = match.Protein.ProteinMetadata;
                    if (matchName != null && matchName.Length > MAX_NAME_LENGTH)
                    {
                        proteinInfo = proteinInfo.ChangeName(matchName.Substring(0, MAX_NAME_LENGTH) + "..."); // Not L10N
                    }
                    var alternativeNames = new List <ProteinMetadata>();
                    if (mainName == null)
                    {
                        mainName = proteinInfo;
                    }
                    else
                    {
                        alternativeNames.Add(proteinInfo);
                    }
                    var listItem = new ListViewItem
                    {
                        Text       = ProteinMetadataManager.ProteinModalDisplayText(mainName, Settings.Default.ShowPeptidesDisplayMode),
                        ImageIndex = (int)ImageId.protein,
                        Tag        = new StatementCompletionItem {
                            ProteinInfo = proteinInfo, SearchText = searchText
                        }
                    };

                    StatementCompletionForm.AddDescription(listItem, mainName.TextForMatchTypes(displayMatchTypes), searchText);
                    if (match.Protein.AlternativeNames.Count > 0)
                    {
                        alternativeNames.AddRange(match.Protein.AlternativeNames);
                        StringBuilder tooltip = new StringBuilder(Resources.StatementCompletionTextBox_CreateListViewItems_Alternative_Names);
                        foreach (var altName in alternativeNames)
                        {
                            if (altName.Name == mainName.Name)
                            {
                                continue;
                            }

                            tooltip.AppendLine().Append(altName.TextForMatchTypes(displayMatchTypes.Union(ProteinMatchType.name)));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                    }
                    // We want the sort to be on what we matched in the description, and what follows.
                    var remains = match.Protein.ProteinMetadata.Description ?? string.Empty;
                    int pos     = remains.ToLower().IndexOf(searchText.ToLower(), StringComparison.Ordinal);
                    if (pos > 0)
                    {
                        remains = remains.Substring(pos);
                    }
                    var key = TextUtil.SpaceSeparate(remains, listItem.Text, listItem.ToolTipText);
                    if (!listItems.ContainsKey(key))
                    {
                        listItems.Add(key, listItem);
                    }
                }
            }
            return(new List <ListViewItem>(listItems.Values));
        }
 /// <summary>
 /// Show the statement completion popup with the list of items.
 /// </summary>
 public void ShowStatementCompletionForm(IList<ListViewItem> items)
 {
     if (items.Count == 0)
     {
         HideStatementCompletionForm();
         return;
     }
     bool show = false;
     if (StatementCompletionForm == null)
     {
         StatementCompletionForm = new StatementCompletionForm { TextBox = TextBox };
         StatementCompletionForm.ListView.MouseDown += ListView_MouseDown;
         StatementCompletionForm.ListView.SmallImageList = _imageList;
         show = true;
     }
     StatementCompletionForm.SetListItems(items);
     StatementCompletionForm.ResizeToIdealSize(ScreenRect);
     if (show)
         StatementCompletionForm.Show(TextBox);
 }
        /// <summary>
        /// Create the ordered list of dropdown items, with a rational sort order:
        ///   First present any sequence matches, sorted by sequence
        ///   Then present any name, accession, gene, preferredname, or species metadata matches, sorted by the matched metadata field
        ///   Then present any matches against the description field, sorted by the description text starting at the match location
        /// </summary>
        public static IList <ListViewItem> CreateListViewItems(IList <ProteinMatch> matches, String searchText, ProteinMatchType matchTypes, int maxCount)
        {
            var listItems       = new SortedList <string, ListViewItem>();
            var listUsedMatches = new List <string>();

            // First check for matching by sequence
            foreach (var match in matches)
            {
                if (0 != (matchTypes & match.MatchType & ProteinMatchType.sequence))
                {
                    foreach (DigestedPeptide digestedPeptide in match.DigestedPeptides)
                    {
                        var listItem = new ListViewItem
                        {
                            Text = digestedPeptide.Sequence,
                            Tag  = new StatementCompletionItem
                            {
                                Peptide     = digestedPeptide.Sequence,
                                ProteinInfo = match.Protein.ProteinMetadata,
                                SearchText  = searchText
                            },
                        };
                        StatementCompletionForm.AddDescription(listItem,
                                                               match.Protein.ProteinMetadata.TextForMatchTypes(matchTypes),
                                                               null);
                        listUsedMatches.Add(match.Protein.Name);
                        listItem.ImageIndex = (int)ImageId.peptide;
                        var tooltip = new StringBuilder();
                        tooltip.AppendLine(Resources.StatementCompletionTextBox_CreateListViewItems_Descriptions)
                        .Append(match.Protein.ProteinMetadata.TextForMatchTypes(matchTypes));
                        foreach (var name in match.Protein.AlternativeNames)
                        {
                            tooltip.AppendLine().Append(name.TextForMatchTypes(matchTypes));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                        // Note the leading space in this sort key - we'd like to list sequence matches first
                        var key = TextUtil.SpaceSeparate(" ", listItem.Text, listItem.ToolTipText); // Not L10N
                        if (!listItems.ContainsKey(key))
                        {
                            listItems.Add(key, listItem);
                        }
                    }
                }
            }
            if (listItems.Count >= maxCount)
            {
                return(new List <ListViewItem>(listItems.Values));  // We used to exit here if we had any matches - but that's frustrating when you're not actually trying to match by sequence
            }

            // Decide which field not to display on righthand side, based on what's already showing on the left due to View|Targets|By* menu
            ProteinMatchType displayMatchType = ProteinMatchType.all;

            switch (SequenceTree.ProteinsDisplayMode)
            {
            case ProteinDisplayMode.ByName:
                displayMatchType &= ~ProteinMatchType.name;
                break;

            case ProteinDisplayMode.ByAccession:
                displayMatchType &= ~ProteinMatchType.accession;
                break;

            case ProteinDisplayMode.ByGene:
                displayMatchType &= ~ProteinMatchType.gene;
                break;

            case ProteinDisplayMode.ByPreferredName:
                displayMatchType &= ~ProteinMatchType.preferredName;
                break;
            }

            foreach (var match in matches)
            {
                // Try matching on name, accession etc - cycle through name, accession, preferredName, gene
                for (int bit = 1; bit < (int)ProteinMatchType.all; bit = bit << 1)
                {
                    ProteinMatchType tryType = (ProteinMatchType)bit;
                    if ((tryType != ProteinMatchType.sequence) &&    // We already did sequence
                        (tryType != ProteinMatchType.description) && // And aren't ready for description
                        (0 != (matchTypes & match.MatchType & tryType) &&
                         !listUsedMatches.Contains(match.Protein.Name)))
                    {
                        var listItem = new ListViewItem();
                        // Show description, and any other fields we were searching on
                        if (match.AlternativeName != null)
                        {
                            listItem.Text = PeptideGroupTreeNode.ProteinModalDisplayText(match.AlternativeName, Settings.Default.ShowPeptidesDisplayMode);
                            listItem.Tag  = new StatementCompletionItem {
                                ProteinInfo = match.AlternativeName, SearchText = searchText
                            };
                            StatementCompletionForm.AddDescription(listItem,
                                                                   match.AlternativeName.TextForMatchTypes(displayMatchType & ~ProteinMatchType.name), searchText);
                        }
                        else
                        {
                            listItem.Text = PeptideGroupTreeNode.ProteinModalDisplayText(match.Protein.ProteinMetadata, Settings.Default.ShowPeptidesDisplayMode);
                            listItem.Tag  = new StatementCompletionItem {
                                ProteinInfo = match.Protein.ProteinMetadata, SearchText = searchText
                            };
                            StatementCompletionForm.AddDescription(listItem,
                                                                   match.Protein.ProteinMetadata.TextForMatchTypes(displayMatchType), searchText);
                        }
                        listUsedMatches.Add(match.Protein.Name);
                        listItem.ImageIndex = (int)ImageId.protein;
                        var tooltip = new StringBuilder();
                        tooltip.AppendLine(Resources.StatementCompletionTextBox_CreateListViewItems_Descriptions)
                        .Append(match.Protein.ProteinMetadata.TextForMatchTypes(displayMatchType));
                        foreach (var altName in match.Protein.AlternativeNames)
                        {
                            tooltip.AppendLine().Append(altName.TextForMatchTypes(displayMatchType));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                        // We want the sort to be on the particular bit of metadata that we matched
                        var key = TextUtil.SpaceSeparate(match.Protein.ProteinMetadata.TextForMatchTypes(tryType), listItem.Text, listItem.ToolTipText);
                        if (!listItems.ContainsKey(key))
                        {
                            listItems.Add(key, listItem);
                        }
                        break;
                    }
                }
            }
            if (listItems.Count >= maxCount)
            {
                return(new List <ListViewItem>(listItems.Values));  // We used to exit here if we had any matches - but that's frustrating when you're not actually trying to match by sequence
            }

            // Any matches by description?
            foreach (var match in matches)
            {
                if ((0 != (match.MatchType & ProteinMatchType.description)) &&
                    !listUsedMatches.Contains(match.Protein.Name))
                {
                    ProteinMetadata mainName    = match.AlternativeDescription;
                    string          matchName   = match.Protein.Name;
                    var             proteinInfo = match.Protein.ProteinMetadata;
                    if (matchName.Length > MAX_NAME_LENGTH)
                    {
                        proteinInfo = proteinInfo.ChangeName(matchName.Substring(0, MAX_NAME_LENGTH) + "..."); // Not L10N
                    }
                    var alternativeNames = new List <ProteinMetadata>();
                    if (mainName == null)
                    {
                        mainName = proteinInfo;
                    }
                    else
                    {
                        alternativeNames.Add(proteinInfo);
                    }
                    var listItem = new ListViewItem
                    {
                        Text       = PeptideGroupTreeNode.ProteinModalDisplayText(mainName, Settings.Default.ShowPeptidesDisplayMode),
                        ImageIndex = (int)ImageId.protein,
                        Tag        = new StatementCompletionItem {
                            ProteinInfo = proteinInfo, SearchText = searchText
                        }
                    };

                    StatementCompletionForm.AddDescription(listItem, mainName.TextForMatchTypes(displayMatchType), searchText);
                    if (match.Protein.AlternativeNames.Count > 0)
                    {
                        alternativeNames.AddRange(match.Protein.AlternativeNames);
                        StringBuilder tooltip = new StringBuilder(Resources.StatementCompletionTextBox_CreateListViewItems_Alternative_Names);
                        foreach (var altName in alternativeNames)
                        {
                            if (altName.Name == mainName.Name)
                            {
                                continue;
                            }

                            tooltip.AppendLine().Append(altName.TextForMatchTypes(displayMatchType | ProteinMatchType.name));
                        }
                        listItem.ToolTipText = StripTabs(tooltip.ToString());
                    }
                    // We want the sort to be on what we matched in the description, and what follows.
                    var remains = match.Protein.ProteinMetadata.Description;
                    int pos     = remains.ToLower().IndexOf(searchText.ToLower(), StringComparison.Ordinal);
                    if (pos > 0)
                    {
                        remains = remains.Substring(pos);
                    }
                    var key = TextUtil.SpaceSeparate(remains, listItem.Text, listItem.ToolTipText);
                    if (!listItems.ContainsKey(key))
                    {
                        listItems.Add(key, listItem);
                    }
                }
            }
            return(new List <ListViewItem>(listItems.Values));
        }