Ejemplo n.º 1
0
        internal static CompletionListFilterResult DefaultFilterItems(ICompletionDataList dataList, IReadOnlyList <int> currentFilteredItems, string oldCompletionString, string completionString, CompletionDataMatcher matcher = null)
        {
            List <int> filteredItems;
            var        newCategories = new List <CategorizedCompletionItems> ();

            matcher = matcher ?? new CompletionDataMatcher {
                StringMatcher = CompletionMatcher.CreateCompletionMatcher(completionString), MatcherId = -1, MatchString = completionString
            };

            if (oldCompletionString == null || !completionString.StartsWith(oldCompletionString, StringComparison.Ordinal))
            {
                // We are filtering the list from scratch (not reusing previous results)
                // This is the most slow operation since we may have to filter a very large amount of items.
                // To improve performance, when there are many items, we try to parallelize the filtering

                // Use multiple threads when we can split the work in chunks of at least 4000 items.
                int numFilterThreads = Math.Max(Math.Min(dataList.Count / 4000, Environment.ProcessorCount / 2), 1);

                // When completion string is empty the matching algorithm is not executed, so there is no need to parallelize
                if (string.IsNullOrEmpty(completionString))
                {
                    numFilterThreads = 1;
                }

                filteredItems = new List <int> ();

                int slice   = dataList.Count / numFilterThreads;
                var results = new(Task, List <int>) [numFilterThreads - 1];
Ejemplo n.º 2
0
        public void FilterWords()
        {
            filteredItems.Clear();
            categories.Clear();
            var matcher = CompletionMatcher.CreateCompletionMatcher(CompletionString);

            for (int newSelection = 0; newSelection < win.DataProvider.ItemCount; newSelection++)
            {
                if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                {
                    CompletionCategory completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                    GetCategory(completionCategory).Items.Add(filteredItems.Count);
                    filteredItems.Add(newSelection);
                }
            }
            categories.Sort(delegate(Category left, Category right) {
                return(right.CompletionCategory != null ? right.CompletionCategory.CompareTo(left.CompletionCategory) : -1);
            });

            SelectFirstItemInCategory();
            CalcVisibleRows();
            UpdatePage();

            OnWordsFiltered(EventArgs.Empty);
        }
Ejemplo n.º 3
0
        public void FilterWords()
        {
            categories.Clear();
            var matcher = CompletionMatcher.CreateCompletionMatcher(CompletionString);

            if (oldCompletionString == null || !CompletionString.StartsWith(oldCompletionString))
            {
                filteredItems.Clear();
                for (int newSelection = 0; newSelection < win.DataProvider.ItemCount; newSelection++)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            else
            {
                var oldItems = filteredItems;
                filteredItems = new List <int> ();
                foreach (int newSelection in oldItems)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }

            filteredItems.Sort(delegate(int left, int right) {
                var lt = win.DataProvider.GetText(left);
                var rt = win.DataProvider.GetText(right);

/*				int r1;
 *                              int r2;
 *                              matcher.CalcMatchRank (lt, out r1);
 *                              matcher.CalcMatchRank (rt, out r2);
 *                              if (r1 == r2) {
 *                                      if (lt.Length != rt.Length)
 *                                              return lt.Length.CompareTo (rt.Length);*/
                return(lt.CompareTo(rt));

/*				}
 *                              return r1.CompareTo (r2);*/
            });
            categories.Sort(delegate(Category left, Category right) {
                return(left.CompletionCategory != null ? left.CompletionCategory.CompareTo(right.CompletionCategory) : -1);
            });

            SelectFirstItemInCategory();
            CalcVisibleRows();
            UpdatePage();

            OnWordsFiltered(EventArgs.Empty);
            oldCompletionString = CompletionString;
        }
Ejemplo n.º 4
0
        public void FilterWords()
        {
            categories.Clear();
            var matcher = CompletionMatcher.CreateCompletionMatcher(CompletionString);

            if (oldCompletionString == null || !CompletionString.StartsWith(oldCompletionString))
            {
                filteredItems.Clear();
                for (int newSelection = 0; newSelection < win.DataProvider.ItemCount; newSelection++)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            else
            {
                var oldItems = filteredItems;
                filteredItems = new List <int> ();
                foreach (int newSelection in oldItems)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }

            filteredItems.Sort(delegate(int left, int right) {
                var lt     = win.DataProvider.GetText(left);
                var rt     = win.DataProvider.GetText(right);
                var result = lt.CompareTo(rt);
                if (result == 0)
                {
                    return(right.CompareTo(left));
                }
                return(result);
            });
            categories.Sort(delegate(Category left, Category right) {
                return(left.CompletionCategory != null ? left.CompletionCategory.CompareTo(right.CompletionCategory) : -1);
            });

            SelectFirstItemInCategory();
            CalcVisibleRows();
            SetAdjustments();

            OnWordsFiltered(EventArgs.Empty);
            oldCompletionString = CompletionString;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets a code completion matcher for the provided string. It will try to reuse an existing one.
        /// </summary>
        CompletionDataMatcher GetCompletionDataMatcher(string partialWord)
        {
            // It keeps the last used matcher in a field, and will reuse it if the requested word doesn't change.
            // 'partialWord' doesn't usually change during the lifetime of CompletionDataList, so in general
            // the same matcher will be used by all calculations required for a key press

            if (lastMatcher != null && partialWord == lastMatcher.MatchString)
            {
                return(lastMatcher);
            }

            return(lastMatcher = new CompletionDataMatcher {
                MatcherId = lastMatcherId++,
                StringMatcher = CompletionMatcher.CreateCompletionMatcher(partialWord),
                MatchString = partialWord
            });
        }
Ejemplo n.º 6
0
 public WordComparer(string filterWord)
 {
     this.filterWord = filterWord ?? "";
     matcher         = CompletionMatcher.CreateCompletionMatcher(filterWord);
 }
Ejemplo n.º 7
0
        static CompletionListFilterResult DefaultFilterWords(ICompletionDataList dataList, List <int> filteredItems, string oldCompletionString, string CompletionString)
        {
            var newCategories = new List <CategorizedCompletionItems> ();
            var matcher       = CompletionMatcher.CreateCompletionMatcher(CompletionString);

            if (oldCompletionString == null || !CompletionString.StartsWith(oldCompletionString, StringComparison.Ordinal))
            {
                filteredItems.Clear();
                for (int newSelection = 0; newSelection < dataList.Count; newSelection++)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(dataList [newSelection].DisplayText))
                    {
                        var completionCategory = dataList [newSelection].CompletionCategory;
                        GetCategory(newCategories, completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            else
            {
                var oldItems = filteredItems;
                filteredItems = new List <int> ();
                foreach (int newSelection in oldItems)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(dataList [newSelection].DisplayText))
                    {
                        var completionCategory = dataList [newSelection].CompletionCategory;
                        GetCategory(newCategories, completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            filteredItems.Sort(delegate(int left, int right) {
                int rank1, rank2;
                var data1 = dataList [left];
                var data2 = dataList [right];
                if (data1 == null || data2 == null)
                {
                    return(0);
                }
                if (data1.PriorityGroup != data2.PriorityGroup)
                {
                    return(data2.PriorityGroup.CompareTo(data1.PriorityGroup));
                }
                if (string.IsNullOrEmpty(CompletionString))
                {
                    return(CompareTo(dataList, left, right));
                }

                if (!matcher.CalcMatchRank(data1.CompletionText, out rank1))
                {
                    return(0);
                }
                if (!matcher.CalcMatchRank(data2.CompletionText, out rank2))
                {
                    return(0);
                }

                return(rank2.CompareTo(rank1));
            });

            // put the item from a lower priority group with the highest match rank always to position #2
            if (filteredItems.Count > 0)
            {
                int idx = 0;
                int rank;
                var data     = dataList[filteredItems [0]];
                int firstGrp = data.PriorityGroup;
                matcher.CalcMatchRank(data.CompletionText, out rank);
                for (int i = 1; i < filteredItems.Count; i++)
                {
                    var curData = dataList[filteredItems [i]];
                    if (curData.PriorityGroup == firstGrp)
                    {
                        continue;
                    }
                    int curRank;
                    matcher.CalcMatchRank(curData.CompletionText, out curRank);
                    if (curRank > rank)
                    {
                        idx  = i;
                        rank = curRank;
                    }
                }

                if (idx != 0)
                {
                    var tmp = filteredItems [idx];
                    for (int i = idx; i > 1; i--)
                    {
                        filteredItems [i] = filteredItems [i - 1];
                    }
                    filteredItems [1] = tmp;
                }
            }

            newCategories.Sort(delegate(CategorizedCompletionItems left, CategorizedCompletionItems right) {
                if (left.CompletionCategory == null)
                {
                    return(1);
                }
                if (right.CompletionCategory == null)
                {
                    return(-1);
                }

                return(left.CompletionCategory.CompareTo(right.CompletionCategory));
            });

            return(new CompletionListFilterResult(filteredItems, newCategories));
        }
Ejemplo n.º 8
0
        protected int FindMatchedEntry(string partialWord, out bool hasMismatches)
        {
            // default - word with highest match rating in the list.
            hasMismatches = true;
            int idx = -1;

            StringMatcher matcher = null;

            if (!string.IsNullOrEmpty(partialWord))
            {
                matcher = CompletionMatcher.CreateCompletionMatcher(partialWord);
                string bestWord          = null;
                int    bestRank          = int.MinValue;
                int    bestIndex         = 0;
                int    bestIndexPriority = int.MinValue;
                for (int i = 0; i < list.filteredItems.Count; i++)
                {
                    int index = list.filteredItems [i];
                    var data  = DataProvider.GetCompletionData(index);
                    if (bestIndexPriority > data.PriorityGroup)
                    {
                        continue;
                    }
                    string text = data.DisplayText;
                    int    rank;
                    if (!matcher.CalcMatchRank(text, out rank))
                    {
                        continue;
                    }
                    if (rank > bestRank || data.PriorityGroup > bestIndexPriority)
                    {
                        bestWord          = text;
                        bestRank          = rank;
                        bestIndex         = i;
                        bestIndexPriority = data.PriorityGroup;
                    }
                }

                if (bestWord != null)
                {
                    idx           = bestIndex;
                    hasMismatches = false;
                    // exact match found.
                    if (string.Compare(bestWord, partialWord ?? "", true) == 0)
                    {
                        return(idx);
                    }
                }
            }

            CompletionData currentData;
            int            bestMruIndex;

            if (idx >= 0)
            {
                currentData  = completionDataList [list.filteredItems [idx]];
                bestMruIndex = cache.GetIndex(currentData);
            }
            else
            {
                bestMruIndex = int.MaxValue;
                currentData  = null;
            }
            for (int i = 0; i < list.filteredItems.Count; i++)
            {
                var mruData     = completionDataList [list.filteredItems [i]];
                int curMruIndex = cache.GetIndex(mruData);
                if (curMruIndex == 1)
                {
                    continue;
                }
                if (curMruIndex < bestMruIndex)
                {
                    int r1 = 0, r2 = 0;
                    if (currentData == null || matcher != null && matcher.CalcMatchRank(mruData.DisplayText, out r1) && matcher.CalcMatchRank(currentData.DisplayText, out r2))
                    {
                        if (r1 >= r2 || PartialWord.Length <= 1)
                        {
                            bestMruIndex = curMruIndex;
                            idx          = i;
                            currentData  = mruData;
                        }
                    }
                }
            }
            return(idx);
        }
Ejemplo n.º 9
0
        public virtual int [] GetHighlightedIndices(CompletionData completionData, string completionString)
        {
            var matcher = CompletionMatcher.CreateCompletionMatcher(completionString);

            return(matcher.GetMatch(completionData.DisplayText));
        }
Ejemplo n.º 10
0
        public virtual CompletionSelectionStatus FindMatchedEntry(ICompletionDataList completionDataList, MruCache cache, string partialWord, List <int> filteredItems)
        {
            // default - word with highest match rating in the list.
            int idx = -1;

            if (DefaultCompletionString != null && DefaultCompletionString.StartsWith(partialWord, StringComparison.OrdinalIgnoreCase))
            {
                partialWord = DefaultCompletionString;
            }
            StringMatcher matcher = null;

            if (!string.IsNullOrEmpty(partialWord))
            {
                matcher = CompletionMatcher.CreateCompletionMatcher(partialWord);
                string bestWord          = null;
                int    bestRank          = int.MinValue;
                int    bestIndex         = 0;
                int    bestIndexPriority = int.MinValue;
                for (int i = 0; i < filteredItems.Count; i++)
                {
                    int index = filteredItems [i];
                    var data  = completionDataList [index];
                    if (bestIndexPriority > data.PriorityGroup)
                    {
                        continue;
                    }
                    string text = data.DisplayText;
                    int    rank;
                    if (!matcher.CalcMatchRank(text, out rank))
                    {
                        continue;
                    }
                    if (rank > bestRank || data.PriorityGroup > bestIndexPriority)
                    {
                        bestWord          = text;
                        bestRank          = rank;
                        bestIndex         = i;
                        bestIndexPriority = data.PriorityGroup;
                    }
                }

                if (bestWord != null)
                {
                    idx = bestIndex;
                    // exact match found.
                    if (string.Compare(bestWord, partialWord ?? "", true) == 0)
                    {
                        return(new CompletionSelectionStatus(idx));
                    }
                }
            }

            CompletionData currentData;
            int            bestMruIndex;

            if (idx >= 0)
            {
                currentData  = completionDataList [filteredItems [idx]];
                bestMruIndex = cache.GetIndex(currentData);
            }
            else
            {
                bestMruIndex = int.MaxValue;
                currentData  = null;
            }
            for (int i = 0; i < filteredItems.Count; i++)
            {
                var mruData     = completionDataList [filteredItems [i]];
                int curMruIndex = cache.GetIndex(mruData);
                if (curMruIndex == 1)
                {
                    continue;
                }
                if (curMruIndex < bestMruIndex)
                {
                    int r1 = 0, r2 = 0;
                    if (currentData == null || matcher != null && matcher.CalcMatchRank(mruData.DisplayText, out r1) && matcher.CalcMatchRank(currentData.DisplayText, out r2))
                    {
                        if (r1 >= r2 || partialWord.Length == 0 || partialWord.Length == 1 && mruData.DisplayText [0] == partialWord [0])
                        {
                            bestMruIndex = curMruIndex;
                            idx          = i;
                            currentData  = mruData;
                        }
                    }
                }
            }
            return(new CompletionSelectionStatus(idx));
        }
Ejemplo n.º 11
0
        protected int FindMatchedEntry(string partialWord, out bool hasMismatches)
        {
            // default - word with highest match rating in the list.
            hasMismatches = true;
            if (partialWord == null)
            {
                return(-1);
            }

            int    idx       = -1;
            var    matcher   = CompletionMatcher.CreateCompletionMatcher(partialWord);
            string bestWord  = null;
            int    bestRank  = int.MinValue;
            int    bestIndex = 0;

            if (!string.IsNullOrEmpty(partialWord))
            {
                for (int i = 0; i < list.filteredItems.Count; i++)
                {
                    int    index = list.filteredItems[i];
                    string text  = DataProvider.GetText(index);
                    int    rank;
                    if (!matcher.CalcMatchRank(text, out rank))
                    {
                        continue;
                    }
                    if (rank > bestRank)
                    {
                        bestWord  = text;
                        bestRank  = rank;
                        bestIndex = i;
                    }
                }
            }
            if (bestWord != null)
            {
                idx           = bestIndex;
                hasMismatches = false;
                // exact match found.
                if (string.Compare(bestWord, partialWord ?? "", true) == 0)
                {
                    return(idx);
                }
            }

            if (string.IsNullOrEmpty(partialWord) || partialWord.Length <= 2)
            {
                // Search for history matches.
                string historyWord;
                if (wordHistory.TryGetValue(partialWord, out historyWord))
                {
                    for (int xIndex = 0; xIndex < list.filteredItems.Count; xIndex++)
                    {
                        string currentWord = DataProvider.GetCompletionText(list.filteredItems[xIndex]);
                        if (currentWord == historyWord)
                        {
                            idx = xIndex;
                            break;
                        }
                    }
                }
            }
            return(idx);
        }
Ejemplo n.º 12
0
        public void FilterWords()
        {
            var newCategories = new List <Category> ();
            var matcher       = CompletionMatcher.CreateCompletionMatcher(CompletionString);

            if (oldCompletionString == null || !CompletionString.StartsWith(oldCompletionString, StringComparison.Ordinal))
            {
                filteredItems.Clear();
                for (int newSelection = 0; newSelection < win.DataProvider.ItemCount; newSelection++)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(newCategories, completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            else
            {
                var oldItems = filteredItems;
                filteredItems = new List <int> ();
                foreach (int newSelection in oldItems)
                {
                    if (string.IsNullOrEmpty(CompletionString) || matcher.IsMatch(win.DataProvider.GetText(newSelection)))
                    {
                        var completionCategory = win.DataProvider.GetCompletionCategory(newSelection);
                        GetCategory(newCategories, completionCategory).Items.Add(newSelection);
                        filteredItems.Add(newSelection);
                    }
                }
            }
            filteredItems.Sort(delegate(int left, int right) {
                int rank1, rank2;
                var data1 = win.DataProvider.GetCompletionData(left);
                var data2 = win.DataProvider.GetCompletionData(right);
                if (data1 == null || data2 == null)
                {
                    return(0);
                }
                if (data1.PriorityGroup != data2.PriorityGroup)
                {
                    return(data2.PriorityGroup.CompareTo(data1.PriorityGroup));
                }
                if (string.IsNullOrEmpty(CompletionString))
                {
                    return(win.DataProvider.CompareTo(left, right));
                }

                if (!matcher.CalcMatchRank(data1.CompletionText, out rank1))
                {
                    return(0);
                }
                if (!matcher.CalcMatchRank(data2.CompletionText, out rank2))
                {
                    return(0);
                }

                return(rank2.CompareTo(rank1));
            });

            // put the item from a lower priority group with the highest match rank always to position #2
            if (filteredItems.Count > 0)
            {
                int idx = 0;
                int rank;
                var data     = win.DataProvider.GetCompletionData(filteredItems [0]);
                int firstGrp = data.PriorityGroup;
                matcher.CalcMatchRank(data.CompletionText, out rank);
                for (int i = 1; i < filteredItems.Count; i++)
                {
                    var curData = win.DataProvider.GetCompletionData(filteredItems [i]);
                    if (curData.PriorityGroup == firstGrp)
                    {
                        continue;
                    }
                    int curRank;
                    matcher.CalcMatchRank(curData.CompletionText, out curRank);
                    if (curRank > rank)
                    {
                        idx  = i;
                        rank = curRank;
                    }
                }

                if (idx != 0)
                {
                    var tmp = filteredItems [idx];
                    for (int i = idx; i > 1; i--)
                    {
                        filteredItems [i] = filteredItems [i - 1];
                    }
                    filteredItems [1] = tmp;
                }
            }

            newCategories.Sort(delegate(Category left, Category right) {
                if (left.CompletionCategory == null)
                {
                    return(1);
                }
                if (right.CompletionCategory == null)
                {
                    return(-1);
                }

                return(left.CompletionCategory.CompareTo(right.CompletionCategory));
            });
            categories = newCategories;

            //SelectFirstItemInCategory ();
            CalcVisibleRows();
            SetAdjustments();

            OnWordsFiltered(EventArgs.Empty);
            oldCompletionString = CompletionString;
        }
Ejemplo n.º 13
0
        protected override bool OnExposeEvent(Gdk.EventExpose args)
        {
            using (var context = Gdk.CairoHelper.Create(args.Window)) {
                var scalef = GtkWorkarounds.GetScaleFactor(this);
                context.LineWidth = 1;
                var alloc  = Allocation;
                int width  = alloc.Width;
                int height = alloc.Height;
                context.Rectangle(args.Area.X, args.Area.Y, args.Area.Width, args.Area.Height);
                var backgroundColor = Styles.CodeCompletion.BackgroundColor.ToCairoColor();
                var textColor       = Styles.CodeCompletion.TextColor.ToCairoColor();
                var categoryColor   = Styles.CodeCompletion.CategoryColor.ToCairoColor();
                context.SetSourceColor(backgroundColor);
                context.Fill();
                int xpos = iconTextSpacing;
                int yPos = (int)-vadj.Value;
                //when there are no matches, display a message to indicate that the completion list is still handling input
                if (filteredItems.Count == 0)
                {
                    context.Rectangle(0, yPos, width, height - yPos);
                    context.SetSourceColor(backgroundColor);
                    context.Stroke();
                    noMatchLayout.SetText(win.DataProvider.ItemCount == 0 ? NoSuggestionsMsg : NoMatchesMsg);
                    int lWidth, lHeight;
                    noMatchLayout.GetPixelSize(out lWidth, out lHeight);
                    context.SetSourceColor(textColor);
                    context.MoveTo((width - lWidth) / 2, yPos + (height - lHeight - yPos) / 2 - lHeight / 2);
                    Pango.CairoHelper.ShowLayout(context, noMatchLayout);
                    return(false);
                }

                var matcher = CompletionMatcher.CreateCompletionMatcher(CompletionString);
                Iterate(true, ref yPos, delegate(Category category, int ypos) {
                    if (ypos >= height)
                    {
                        return;
                    }
                    if (ypos < -rowHeight)
                    {
                        return;
                    }

                    //	window.DrawRectangle (this.Style.BackgroundGC (StateType.Insensitive), true, 0, yPos, width, rowHeight);
                    int x = 2;
                    if (category.CompletionCategory != null && !string.IsNullOrEmpty(category.CompletionCategory.Icon))
                    {
                        var icon = ImageService.GetIcon(category.CompletionCategory.Icon, IconSize.Menu);
                        context.DrawImage(this, icon, 0, ypos);
                        x = (int)icon.Width + 4;
                    }
                    context.Rectangle(0, ypos, Allocation.Width, rowHeight);
                    context.SetSourceColor(backgroundColor);
                    context.Fill();


                    //					layout.SetMarkup ("<span weight='bold' foreground='#AAAAAA'>" + (category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized") + "</span>");
                    //					window.DrawLayout (textGCInsensitive, x - 1, ypos + 1 + (rowHeight - py) / 2, layout);
                    //					layout.SetMarkup ("<span weight='bold'>" + (category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized") + "</span>");
                    categoryLayout.SetMarkup((category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized"));
                    int px, py;
                    categoryLayout.GetPixelSize(out px, out py);
                    context.MoveTo(x, ypos + (rowHeight - py) / 2);
                    context.SetSourceColor(categoryColor);
                    Pango.CairoHelper.ShowLayout(context, categoryLayout);
                }, delegate(Category curCategory, int item, int itemidx, int ypos) {
                    if (ypos >= height)
                    {
                        return(false);
                    }
                    if (ypos < -rowHeight)
                    {
                        return(true);
                    }
                    const int categoryModeItemIndenting = 0;
                    if (InCategoryMode && curCategory != null && curCategory.CompletionCategory != null)
                    {
                        xpos = iconTextSpacing + categoryModeItemIndenting;
                    }
                    else
                    {
                        xpos = iconTextSpacing;
                    }
                    string markup      = win.DataProvider.HasMarkup(item) ? (win.DataProvider.GetMarkup(item) ?? "&lt;null&gt;") : GLib.Markup.EscapeText(win.DataProvider.GetText(item) ?? "<null>");
                    string description = win.DataProvider.GetDescription(item, item == SelectedItem);

                    if (string.IsNullOrEmpty(description))
                    {
                        layout.SetMarkup(markup);
                    }
                    else
                    {
                        layout.SetMarkup(markup + " " + description);
                    }

                    string text = win.DataProvider.GetText(item);

                    if (!string.IsNullOrEmpty(text))
                    {
                        int [] matchIndices = matcher.GetMatch(text);
                        if (matchIndices != null)
                        {
                            Pango.AttrList attrList = layout.Attributes ?? new Pango.AttrList();
                            for (int newSelection = 0; newSelection < matchIndices.Length; newSelection++)
                            {
                                int idx  = matchIndices [newSelection];
                                var bold = new AttrWeight(Weight.Bold);

                                bold.StartIndex = (uint)idx;
                                bold.EndIndex   = (uint)(idx + 1);
                                attrList.Insert(bold);

                                if (item != SelectedItem)
                                {
                                    var highlightColor = (item == SelectedItem) ? Styles.CodeCompletion.SelectionHighlightColor : Styles.CodeCompletion.HighlightColor;
                                    var fg             = new AttrForeground((ushort)(highlightColor.Red * ushort.MaxValue), (ushort)(highlightColor.Green * ushort.MaxValue), (ushort)(highlightColor.Blue * ushort.MaxValue));
                                    fg.StartIndex      = (uint)idx;
                                    fg.EndIndex        = (uint)(idx + 1);
                                    attrList.Insert(fg);
                                }
                            }
                            layout.Attributes = attrList;
                        }
                    }

                    Xwt.Drawing.Image icon = win.DataProvider.GetIcon(item);
                    int iconHeight, iconWidth;
                    if (icon != null)
                    {
                        if (item == SelectedItem)
                        {
                            icon = icon.WithStyles("sel");
                        }
                        iconWidth  = (int)icon.Width;
                        iconHeight = (int)icon.Height;
                    }
                    else if (!Gtk.Icon.SizeLookup(IconSize.Menu, out iconWidth, out iconHeight))
                    {
                        iconHeight = iconWidth = 24;
                    }

                    int wi, he, typos, iypos;
                    layout.GetPixelSize(out wi, out he);


                    typos = he < rowHeight ? ypos + (int)Math.Ceiling((rowHeight - he) / 2.0) : ypos;
                    if (scalef <= 1.0)
                    {
                        typos -= 1;                 // 1px up on non HiDPI
                    }
                    iypos = iconHeight < rowHeight ? ypos + (rowHeight - iconHeight) / 2 : ypos;
                    if (item == SelectedItem)
                    {
                        var barStyle = SelectionEnabled ? Styles.CodeCompletion.SelectionBackgroundColor : Styles.CodeCompletion.SelectionBackgroundInactiveColor;

                        context.Rectangle(0, ypos, Allocation.Width, rowHeight);
                        context.SetSourceColor(barStyle.ToCairoColor());
                        context.Fill();
                    }

                    if (icon != null)
                    {
                        context.DrawImage(this, icon, xpos, iypos);
                        xpos += iconTextSpacing;
                    }
                    context.SetSourceColor((item == SelectedItem ? Styles.CodeCompletion.SelectionTextColor : Styles.CodeCompletion.TextColor).ToCairoColor());
                    var textXPos = xpos + iconWidth + 2;
                    context.MoveTo(textXPos, typos);
                    layout.Width     = (int)((Allocation.Width - textXPos) * Pango.Scale.PangoScale);
                    layout.Ellipsize = EllipsizeMode.End;
                    Pango.CairoHelper.ShowLayout(context, layout);
                    int textW, textH;
                    layout.GetPixelSize(out textW, out textH);
                    layout.Width     = -1;
                    layout.Ellipsize = EllipsizeMode.None;

                    layout.SetMarkup("");
                    if (layout.Attributes != null)
                    {
                        layout.Attributes.Dispose();
                        layout.Attributes = null;
                    }

                    string rightText = win.DataProvider.GetRightSideDescription(item, item == SelectedItem);
                    if (!string.IsNullOrEmpty(rightText))
                    {
                        layout.SetMarkup(rightText);

                        int w, h;
                        layout.GetPixelSize(out w, out h);
                        const int leftpadding  = 8;
                        const int rightpadding = 3;
                        w    += rightpadding;
                        w     = Math.Min(w, Allocation.Width - textXPos - textW - leftpadding);
                        wi   += w;
                        typos = h < rowHeight ? ypos + (rowHeight - h) / 2 : ypos;
                        if (scalef <= 1.0)
                        {
                            typos -= 1;                             // 1px up on non HiDPI
                        }
                        context.MoveTo(Allocation.Width - w, typos);
                        layout.Width     = (int)(w * Pango.Scale.PangoScale);
                        layout.Ellipsize = EllipsizeMode.End;

                        Pango.CairoHelper.ShowLayout(context, layout);
                        layout.Width     = -1;
                        layout.Ellipsize = EllipsizeMode.None;
                    }

                    if (Math.Min(maxListWidth, wi + xpos + iconWidth + 2) > listWidth)
                    {
                        WidthRequest = listWidth = Math.Min(maxListWidth, wi + xpos + iconWidth + 2 + iconTextSpacing);
                        win.ResetSizes();
                    }
                    else
                    {
                        //workaround for the vscrollbar display - the calculated width needs to be the width ofthe render region.
                        if (Allocation.Width < listWidth)
                        {
                            if (listWidth - Allocation.Width < 30)
                            {
                                WidthRequest = listWidth + listWidth - Allocation.Width;
                                win.ResetSizes();
                            }
                        }
                    }

                    return(true);
                });

                return(false);
            }
        }
Ejemplo n.º 14
0
        protected override bool OnExposeEvent(Gdk.EventExpose args)
        {
            Gdk.Window window = args.Window;
            var        alloc  = Allocation;
            int        width  = alloc.Width;
            int        height = alloc.Height;

            int lineWidth = width - margin * 2;
            int xpos      = margin + padding;
            int yPos      = margin;

            if (PreviewCompletionString)
            {
                layout.SetText(string.IsNullOrEmpty(CompletionString) ? MonoDevelop.Core.GettextCatalog.GetString("Select template") : CompletionString);
                int wi, he;
                layout.GetPixelSize(out wi, out he);
                window.DrawRectangle(this.Style.BaseGC(StateType.Insensitive), true, margin, yPos, lineWidth, he + padding);
                window.DrawLayout(string.IsNullOrEmpty(CompletionString) ? this.Style.TextGC(StateType.Insensitive) : this.Style.TextGC(StateType.Normal), xpos, yPos, layout);
                yPos += rowHeight;
            }

            //when there are no matches, display a message to indicate that the completion list is still handling input
            if (filteredItems.Count == 0)
            {
                Gdk.GC gc = new Gdk.GC(window);
                gc.RgbFgColor = new Gdk.Color(0xff, 0xbc, 0xc1);
                window.DrawRectangle(gc, true, 0, yPos, width, height - yPos);
                layout.SetText(win.DataProvider.ItemCount == 0? NoSuggestionsMsg : NoMatchesMsg);
                int lWidth, lHeight;
                layout.GetPixelSize(out lWidth, out lHeight);
                gc.RgbFgColor = new Gdk.Color(0, 0, 0);
                window.DrawLayout(gc, (width - lWidth) / 2, yPos + (height - lHeight - yPos) / 2, layout);
                gc.Dispose();
                return(true);
            }

            var textGCInsensitive = this.Style.TextGC(StateType.Insensitive);
            var textGCNormal      = this.Style.TextGC(StateType.Normal);
            var fgGCNormal        = this.Style.ForegroundGC(StateType.Normal);
            var matcher           = CompletionMatcher.CreateCompletionMatcher(CompletionString);
            var highlightColor    = HighlightColor;

            Iterate(true, ref yPos, delegate(Category category, int ypos) {
                if (ypos >= height - margin)
                {
                    return;
                }

                //	window.DrawRectangle (this.Style.BackgroundGC (StateType.Insensitive), true, 0, yPos, width, rowHeight);

                Gdk.Pixbuf icon = ImageService.GetPixbuf(category.CompletionCategory.Icon, IconSize.Menu);
                window.DrawPixbuf(fgGCNormal, icon, 0, 0, margin, ypos, icon.Width, icon.Height, Gdk.RgbDither.None, 0, 0);

                layout.SetMarkup("<span weight='bold'>" + category.CompletionCategory.DisplayText + "</span>");
                window.DrawLayout(textGCInsensitive, icon.Width + 4, ypos, layout);
                layout.SetMarkup("");
            }, delegate(Category curCategory, int item, int ypos) {
                if (ypos >= height - margin)
                {
                    return(false);
                }
                int itemIndex = filteredItems[item];
                if (InCategoryMode && curCategory != null && curCategory.CompletionCategory != null)
                {
                    xpos = margin + padding + 8;
                }
                else
                {
                    xpos = margin + padding;
                }
                string markup      = win.DataProvider.HasMarkup(itemIndex) ? (win.DataProvider.GetMarkup(itemIndex) ?? "&lt;null&gt;") : GLib.Markup.EscapeText(win.DataProvider.GetText(itemIndex) ?? "<null>");
                string description = win.DataProvider.GetDescription(itemIndex);

                if (string.IsNullOrEmpty(description))
                {
                    layout.SetMarkup(markup);
                }
                else
                {
                    if (item == selection)
                    {
                        layout.SetMarkup(markup + " " + description);
                    }
                    else
                    {
                        layout.SetMarkup(markup + " <span foreground=\"darkgray\">" + description + "</span>");
                    }
                }
                int mw, mh;
                layout.GetPixelSize(out mw, out mh);
                if (mw > listWidth)
                {
                    WidthRequest     = listWidth = mw;
                    win.WidthRequest = win.Allocation.Width + mw - width;
                    win.QueueResize();
                }

                string text = win.DataProvider.GetText(itemIndex);

                if ((!SelectionEnabled || item != selection) && !string.IsNullOrEmpty(text))
                {
                    int[] matchIndices = matcher.GetMatch(text);
                    if (matchIndices != null)
                    {
                        Pango.AttrList attrList = layout.Attributes ?? new Pango.AttrList();
                        for (int newSelection = 0; newSelection < matchIndices.Length; newSelection++)
                        {
                            int idx = matchIndices[newSelection];
                            Pango.AttrForeground fg = new Pango.AttrForeground(highlightColor.Red, highlightColor.Green, highlightColor.Blue);
                            fg.StartIndex           = (uint)idx;
                            fg.EndIndex             = (uint)(idx + 1);
                            attrList.Insert(fg);
                        }
                        layout.Attributes = attrList;
                    }
                }

                Gdk.Pixbuf icon = win.DataProvider.GetIcon(itemIndex);
                int iconHeight, iconWidth;
                if (icon != null)
                {
                    iconWidth  = icon.Width;
                    iconHeight = icon.Height;
                }
                else if (!Gtk.Icon.SizeLookup(Gtk.IconSize.Menu, out iconWidth, out iconHeight))
                {
                    iconHeight = iconWidth = 24;
                }

                int wi, he, typos, iypos;
                layout.GetPixelSize(out wi, out he);
                typos = he < rowHeight ? ypos + (rowHeight - he) / 2 : ypos;
                iypos = iconHeight < rowHeight ? ypos + (rowHeight - iconHeight) / 2 : ypos;
                if (item == selection)
                {
                    if (SelectionEnabled)
                    {
                        window.DrawRectangle(this.Style.BaseGC(StateType.Selected), true, margin, ypos, lineWidth, he + padding);
                        window.DrawLayout(this.Style.TextGC(StateType.Selected), xpos + iconWidth + 2, typos, layout);
                    }
                    else
                    {
                        window.DrawRectangle(this.Style.DarkGC(StateType.Prelight), false, margin, ypos, lineWidth - 1, he + padding - 1);
                        window.DrawLayout(textGCNormal, xpos + iconWidth + 2, typos, layout);
                    }
                }
                else
                {
                    window.DrawLayout(textGCNormal, xpos + iconWidth + 2, typos, layout);
                }
                if (icon != null)
                {
                    window.DrawPixbuf(fgGCNormal, icon, 0, 0, xpos, iypos, iconWidth, iconHeight, Gdk.RgbDither.None, 0, 0);
                }

                layout.SetMarkup("");
                if (layout.Attributes != null)
                {
                    layout.Attributes.Dispose();
                    layout.Attributes = null;
                }
                return(true);
            });

            /*
             * int n = 0;
             * while (ypos < winHeight - margin && (page + n) < filteredItems.Count) {
             *
             *      bool hasMarkup = win.DataProvider.HasMarkup (filteredItems[page + n]);
             *      if (hasMarkup) {
             *              layout.SetMarkup (win.DataProvider.GetMarkup (filteredItems[page + n]) ?? "&lt;null&gt;");
             *      } else {
             *              layout.SetText (win.DataProvider.GetText (filteredItems[page + n]) ?? "<null>");
             *      }
             *      string text = win.DataProvider.GetText (filteredItems[page + n]);
             *      if ((!SelectionEnabled || page + n != selection) && !string.IsNullOrEmpty (text)) {
             *              int[] matchIndices = Match (CompletionString, text);
             *              if (matchIndices != null) {
             *                      Pango.AttrList attrList = layout.Attributes ?? new Pango.AttrList ();
             *                      for (int newSelection = 0; newSelection < matchIndices.Length; newSelection++) {
             *                              int idx = matchIndices[newSelection];
             *                              Pango.AttrForeground fg = new Pango.AttrForeground (0, 0, ushort.MaxValue);
             *                              fg.StartIndex = (uint)idx;
             *                              fg.EndIndex = (uint)(idx + 1);
             *                              attrList.Insert (fg);
             *                      }
             *                      layout.Attributes = attrList;
             *              }
             *      }
             *
             *      Gdk.Pixbuf icon = win.DataProvider.GetIcon (filteredItems[page + n]);
             *      int iconHeight, iconWidth;
             *      if (icon != null) {
             *              iconWidth = icon.Width;
             *              iconHeight = icon.Height;
             *      } else if (!Gtk.Icon.SizeLookup (Gtk.IconSize.Menu, out iconWidth, out iconHeight)) {
             *              iconHeight = iconWidth = 24;
             *      }
             *
             *      int wi, he, typos, iypos;
             *      layout.GetPixelSize (out wi, out he);
             *      typos = he < rowHeight ? ypos + (rowHeight - he) / 2 : ypos;
             *      iypos = iconHeight < rowHeight ? ypos + (rowHeight - iconHeight) / 2 : ypos;
             *      if (page + n == selection) {
             *              if (SelectionEnabled) {
             *                      window.DrawRectangle (this.Style.BaseGC (StateType.Selected), true, margin, ypos, lineWidth, he + padding);
             *                      window.DrawLayout (this.Style.TextGC (StateType.Selected), xpos + iconWidth + 2, typos, layout);
             *              } else {
             *                      window.DrawRectangle (this.Style.DarkGC (StateType.Prelight), false, margin, ypos, lineWidth - 1, he + padding - 1);
             *                      window.DrawLayout (this.Style.TextGC (StateType.Normal), xpos + iconWidth + 2, typos, layout);
             *              }
             *      } else
             *              window.DrawLayout (this.Style.TextGC (StateType.Normal), xpos + iconWidth + 2, typos, layout);
             *      if (icon != null)
             *              window.DrawPixbuf (this.Style.ForegroundGC (StateType.Normal), icon, 0, 0, xpos, iypos, iconWidth, iconHeight, Gdk.RgbDither.None, 0, 0);
             *      ypos += rowHeight;
             *      n++;
             *      if (hasMarkup)
             *              layout.SetMarkup (string.Empty);
             *      if (layout.Attributes != null) {
             *              layout.Attributes.Dispose ();
             *              layout.Attributes = null;
             *      }
             * }
             */
            return(true);
        }
Ejemplo n.º 15
0
        protected override bool OnExposeEvent(Gdk.EventExpose args)
        {
            using (var context = Gdk.CairoHelper.Create(args.Window)) {
                context.LineWidth = 1;
                var alloc  = Allocation;
                int width  = alloc.Width;
                int height = alloc.Height;
                context.Rectangle(args.Area.X, args.Area.Y, args.Area.Width, args.Area.Height);
                context.Color = this.backgroundColor;
                context.Fill();

                int xpos = iconTextSpacing;
                int yPos = (int)-vadj.Value;

                //when there are no matches, display a message to indicate that the completion list is still handling input
                if (filteredItems.Count == 0)
                {
                    context.Rectangle(0, yPos, width, height - yPos);
                    context.Color = backgroundColor;
                    context.Stroke();
                    noMatchLayout.SetText(win.DataProvider.ItemCount == 0 ? NoSuggestionsMsg : NoMatchesMsg);
                    int lWidth, lHeight;
                    noMatchLayout.GetPixelSize(out lWidth, out lHeight);
                    context.Color = textColor;
                    context.MoveTo((width - lWidth) / 2, yPos + (height - lHeight - yPos) / 2 - lHeight);
                    PangoCairoHelper.ShowLayout(context, noMatchLayout);
                    return(false);
                }

                var matcher = CompletionMatcher.CreateCompletionMatcher(CompletionString);
                Iterate(true, ref yPos, delegate(Category category, int ypos) {
                    if (ypos >= height)
                    {
                        return;
                    }
                    if (ypos < -rowHeight)
                    {
                        return;
                    }

                    //	window.DrawRectangle (this.Style.BackgroundGC (StateType.Insensitive), true, 0, yPos, width, rowHeight);
                    int x = 2;
                    if (category.CompletionCategory != null && !string.IsNullOrEmpty(category.CompletionCategory.Icon))
                    {
                        var icon = ImageService.GetPixbuf(category.CompletionCategory.Icon, IconSize.Menu);
                        Gdk.CairoHelper.SetSourcePixbuf(context, icon, 0, ypos);
                        context.Paint();
                        x = icon.Width + 4;
                    }
                    context.Rectangle(0, ypos, Allocation.Width, rowHeight);
                    context.Color = backgroundColor;
                    context.Fill();


//					layout.SetMarkup ("<span weight='bold' foreground='#AAAAAA'>" + (category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized") + "</span>");
//					window.DrawLayout (textGCInsensitive, x - 1, ypos + 1 + (rowHeight - py) / 2, layout);
//					layout.SetMarkup ("<span weight='bold'>" + (category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized") + "</span>");
                    categoryLayout.SetMarkup((category.CompletionCategory != null ? category.CompletionCategory.DisplayText : "Uncategorized"));
                    int px, py;
                    categoryLayout.GetPixelSize(out px, out py);
                    context.MoveTo(x, ypos + (rowHeight - py) / 2);
                    context.Color = textColor;
                    PangoCairoHelper.ShowLayout(context, categoryLayout);
                }, delegate(Category curCategory, int item, int itemidx, int ypos) {
                    if (ypos >= height)
                    {
                        return(false);
                    }
                    if (ypos < -rowHeight)
                    {
                        return(true);
                    }
                    const int categoryModeItemIndenting = 0;
                    if (InCategoryMode && curCategory != null && curCategory.CompletionCategory != null)
                    {
                        xpos = iconTextSpacing + categoryModeItemIndenting;
                    }
                    else
                    {
                        xpos = iconTextSpacing;
                    }
                    string markup      = win.DataProvider.HasMarkup(item) ? (win.DataProvider.GetMarkup(item) ?? "&lt;null&gt;") : GLib.Markup.EscapeText(win.DataProvider.GetText(item) ?? "<null>");
                    string description = win.DataProvider.GetDescription(item);

                    if (string.IsNullOrEmpty(description))
                    {
                        layout.SetMarkup(markup);
                    }
                    else
                    {
                        if (item == SelectedItem)
                        {
                            layout.SetMarkup(markup + " " + description);
                        }
                        else
                        {
                            layout.SetMarkup(markup + " <span foreground=\"darkgray\">" + description + "</span>");
                        }
                    }

                    string text = win.DataProvider.GetText(item);

                    if (!string.IsNullOrEmpty(text))
                    {
                        int[] matchIndices = matcher.GetMatch(text);
                        if (matchIndices != null)
                        {
                            Pango.AttrList attrList = layout.Attributes ?? new Pango.AttrList();
                            for (int newSelection = 0; newSelection < matchIndices.Length; newSelection++)
                            {
                                int idx       = matchIndices [newSelection];
                                var fg        = new AttrForeground((ushort)(highlightColor.R * ushort.MaxValue), (ushort)(highlightColor.G * ushort.MaxValue), (ushort)(highlightColor.B * ushort.MaxValue));
                                fg.StartIndex = (uint)idx;
                                fg.EndIndex   = (uint)(idx + 1);
                                attrList.Insert(fg);
                            }
                            layout.Attributes = attrList;
                        }
                    }

                    Gdk.Pixbuf icon = win.DataProvider.GetIcon(item);
                    int iconHeight, iconWidth;
                    if (icon != null)
                    {
                        iconWidth  = icon.Width;
                        iconHeight = icon.Height;
                    }
                    else if (!Gtk.Icon.SizeLookup(Gtk.IconSize.Menu, out iconWidth, out iconHeight))
                    {
                        iconHeight = iconWidth = 24;
                    }

                    int wi, he, typos, iypos;
                    layout.GetPixelSize(out wi, out he);


                    typos = he < rowHeight ? ypos + (rowHeight - he) / 2 : ypos;
                    iypos = iconHeight < rowHeight ? ypos + (rowHeight - iconHeight) / 2 : ypos;
                    if (item == SelectedItem)
                    {
                        context.Rectangle(0, ypos, Allocation.Width, rowHeight / 2);
                        context.Color = SelectionEnabled ? selectedItemColor.Foreground : selectedItemInactiveColor.Background;
                        context.Fill();
                        context.Rectangle(0, ypos + rowHeight / 2, Allocation.Width, rowHeight / 2);
                        context.Color = SelectionEnabled ? selectedItemColor.Background : selectedItemInactiveColor.Background;
                        context.Fill();

                        context.Rectangle(0.5, ypos + 0.5, Allocation.Width - 1, rowHeight - 1);
                        if (!SelectionEnabled)
                        {
                            context.SetDash(new double[] { 4, 4 }, 0);
                        }
                        context.Color = SelectionEnabled ? selectionBorderColor : selectionBorderInactiveColor;
                        context.Stroke();
                    }

                    if (icon != null)
                    {
                        Gdk.CairoHelper.SetSourcePixbuf(context, icon, xpos, iypos);
                        context.Paint();
                        xpos += iconTextSpacing;
                    }
                    context.Color = textColor;
                    context.MoveTo(xpos + iconWidth + 2, typos);
                    PangoCairoHelper.ShowLayout(context, layout);

                    if (wi + xpos + iconWidth + 2 > listWidth)
                    {
                        WidthRequest = listWidth = wi + xpos + iconWidth + 2 + iconTextSpacing;
                        win.ResetSizes();
                    }
                    else
                    {
                        //workaround for the vscrollbar display - the calculated width needs to be the width ofthe render region.
                        if (Allocation.Width < listWidth)
                        {
                            if (listWidth - Allocation.Width < 30)
                            {
                                WidthRequest = listWidth + listWidth - Allocation.Width;
                                win.ResetSizes();
                            }
                        }
                    }


                    layout.SetMarkup("");
                    if (layout.Attributes != null)
                    {
                        layout.Attributes.Dispose();
                        layout.Attributes = null;
                    }
                    return(true);
                });

                return(false);
            }
        }