private void UpdateEventHandlers(bool?forceEvents)
        {
            bool needEvents = forceEvents.HasValue ? forceEvents.Value : (this.IsVisible || (this.adornmentMatchBrush != null));

            if (needEvents != this.hasEvents)
            {
                this.hasEvents = needEvents;
                if (needEvents)
                {
                    this.textView.LayoutChanged         += OnLayoutChanged;
                    this.textView.Caret.PositionChanged += OnPositionChanged;
                    this.scrollBar.TrackSpanChanged     += OnTrackSpanChanged;

                    //Rescan everything since things might have changed.
                    this.UpdateMarginMatches(true);
                }
                else
                {
                    this.textView.LayoutChanged         -= OnLayoutChanged;
                    this.textView.Caret.PositionChanged -= OnPositionChanged;
                    this.scrollBar.TrackSpanChanged     -= OnTrackSpanChanged;

                    if (this.search != null)
                    {
                        this.search.Abort();
                        this.search = null;
                    }
                    this.highlight     = null;
                    this.highlightSpan = null;
                }
            }
        }
        public async Task <PagedSearchResult <Background> > SearchBackgrounds(BackgroundSearch backgroundSearch)
        {
            var filter = "";

            if (!string.IsNullOrEmpty(backgroundSearch.Name))
            {
                filter = $"Name eq '{backgroundSearch.Name}'";
            }
            if (backgroundSearch.ContentType.HasValue && backgroundSearch.ContentType != ContentType.None)
            {
                if (!string.IsNullOrEmpty(filter))
                {
                    filter = $"{filter} and";
                }
                filter = $"{filter} ContentType eq '{backgroundSearch.ContentType.ToString()}'";
            }

            var query       = new TableQuery <Background>().Where(filter);
            var backgrounds = await _tableStorage.QueryAsync("backgrounds", query);

            switch (backgroundSearch.BackgroundSearchOrdering)
            {
            case BackgroundSearchOrdering.NameAscending:
                backgrounds = backgrounds.OrderBy(p => p.Name);
                break;

            case BackgroundSearchOrdering.NameDescending:
                backgrounds = backgrounds.OrderByDescending(p => p.Name);
                break;

            case BackgroundSearchOrdering.ContentTypeAscending:
                backgrounds = backgrounds.OrderBy(p => p.ContentType);
                break;

            case BackgroundSearchOrdering.ContentTypeDescending:
                backgrounds = backgrounds.OrderByDescending(p => p.ContentType);
                break;
            }

            return(new PagedSearchResult <Background>(backgrounds.ToList(), backgroundSearch.PageSize, backgroundSearch.CurrentPage));
        }
            public static int?GetMatch(string searchText, string text, int offset)
            {
                while (true)
                {
                    int match = text.IndexOf(searchText, offset, StringComparison.Ordinal);
                    if (match == -1)
                    {
                        break;
                    }

                    if (BackgroundSearch.IsCompleteWord(match, searchText.Length, text))
                    {
                        return(match);
                    }

                    //Continue searching where the old search left off.
                    offset = match + 1;
                }

                return(null);
            }
Exemplo n.º 4
0
        private bool UpdateEventHandlers(bool checkEvents, bool wereAdornmentsEnabled = true)
        {
            bool needEvents = checkEvents &&
                              _textView.VisualElement.IsVisible &&
                              (this.MarginActive || this.AdornmentsActive);

            if (needEvents != _hasEvents)
            {
                _hasEvents = needEvents;
                if (needEvents)
                {
                    _editorFormatMap.FormatMappingChanged += OnFormatMappingChanged;
                    _textView.LayoutChanged += OnLayoutChanged;
                    _textView.Selection.SelectionChanged += OnPositionChanged;
                    _scrollBar.Map.MappingChanged        += OnMappingChanged;

                    this.OnFormatMappingChanged(null, null);

                    return(this.UpdateMatches(wereAdornmentsEnabled));
                }
                else
                {
                    _editorFormatMap.FormatMappingChanged -= OnFormatMappingChanged;
                    _textView.LayoutChanged -= OnLayoutChanged;
                    _textView.Selection.SelectionChanged -= OnPositionChanged;
                    _scrollBar.Map.MappingChanged        -= OnMappingChanged;

                    if (_search != null)
                    {
                        _search.Abort();
                        _search = null;
                    }
                    _highlight     = null;
                    _highlightSpan = null;
                }
            }

            return(false);
        }
Exemplo n.º 5
0
            /// <summary>
            /// Search for all instances of <paramref name="searchText"/> in <paramref name="snapshot"/>. Call
            /// <paramref name="completionCallback"/> once the search has completed.
            /// </summary>
            /// <param name="snapshot">Text snapshot in which to search.</param>
            /// <param name="searchText">Test to search for.</param>
            /// <param name="completionCallback">Delegate to call if the search is completed (will be called on the UI thread).</param>
            /// <remarks>The constructor must be called from the UI thread.</remarks>
            public BackgroundSearch(ITextSnapshot snapshot, string searchText, bool matchWholeWord, Action completionCallback)
            {
                this.Snapshot = snapshot;

                ThreadPool.QueueUserWorkItem(delegate(object state)
                {
                    //Lower our priority so that we do not compete with the rendering.
                    System.Threading.Thread.CurrentThread.Priority     = ThreadPriority.Lowest;
                    System.Threading.Thread.CurrentThread.IsBackground = true;

                    List <SnapshotSpan> newMatches = new List <SnapshotSpan>();

                    int start = 0;
                    while (true)
                    {
                        int end     = Math.Min(snapshot.Length, start + MatchMarginElement.SearchBufferSize);
                        string text = snapshot.GetText(start, end - start);

                        int offset = (start == 0) ? 0 : 1;
                        while (true)
                        {
                            int match = text.IndexOf(searchText, offset, StringComparison.Ordinal);
                            if (match == -1)
                            {
                                break;
                            }

                            if (matchWholeWord)
                            {
                                //Make sure the character preceeding the match is a word break
                                //(or the very start of the buffer, which is the only time match can equal 0).
                                if ((match == 0) || !BackgroundSearch.IsWordCharacter(text[match - 1]))
                                {
                                    //Make sure the character after the match is a word break.
                                    //If we're at the end of text, then it is only considered a word break if that is also the very end of the buffer.
                                    if ((match + searchText.Length == text.Length)
                                        ? (end == snapshot.Length)
                                        : !BackgroundSearch.IsWordCharacter(text[match + searchText.Length]))
                                    {
                                        SnapshotSpan matchSpan = new SnapshotSpan(snapshot, match + start, searchText.Length);
                                        newMatches.Add(matchSpan);
                                    }
                                }
                            }
                            else
                            {
                                //Any match is a match.
                                SnapshotSpan matchSpan = new SnapshotSpan(snapshot, match + start, searchText.Length);
                                newMatches.Add(matchSpan);
                            }

                            //Continue searching at the location of the next possible match
                            //(we could add one more since there needs to be one character of whitespace between matches, but
                            //then we'd need an if to guard against placing offset past the end of text).
                            offset = match + searchText.Length;
                        }

                        //Check to see if the search should be aborted because no one cares about the result any more.
                        if (_abort)
                        {
                            return;
                        }

                        if (end == snapshot.Length)
                        {
                            break;  //All done.
                        }
                        //rollback from the end enough so that we can match something that we previously matched at the very end of the
                        //(along with the preceeding character so we can ensure it starts on a word break).
                        start = end - (searchText.Length + 1);
                    }

                    //This should be a thread safe operation since it is atomic
                    _matches = newMatches;

                    completionCallback();
                });
            }
Exemplo n.º 6
0
        /// <summary>
        /// Start a background search for all instances of this.highlight.
        /// </summary>
        /// <returns>
        /// true if a either a search has been queued or if the adornments/margin have been cleared since the highlight was removed.
        /// </returns>
        private bool UpdateMatches(bool wereAdornmentsEnabled = true)
        {
            if (_hasEvents)
            {
                SnapshotSpan?oldHighlightSpan = _highlightSpan;
                string       oldHighlight     = _highlight;

                bool matchWholeWord = _textView.Selection.IsEmpty;
                _highlightSpan = matchWholeWord
                                     ? BackgroundSearch.GetExtentOfWord(_textView.Caret.Position.BufferPosition)
                                     : this.SelectionToHighlightSpan();

                _highlight = (_highlightSpan.HasValue) ? _highlightSpan.Value.GetText() : null;

                //Do a new search if the highlight changed, there is no existing search, or the existing search was on the wrong snapshot.
                if ((_highlight != oldHighlight) || (_search == null) || (_search.Snapshot != _textView.TextSnapshot))
                {
                    //The text of the highlight changes ... restart the search.
                    if (_search != null)
                    {
                        //Stop and blow away the old search (even if it didn't finish, the results are not interesting anymore).
                        _search.Abort();
                        _search = null;
                    }

                    if (_highlight != null)
                    {
                        //The underlying buffer could be very large, meaning that doing the search for all matches on the UI thread
                        //is a bad idea. Do the search on the background thread and use a callback to invalidate the visual when
                        //the entire search has completed.
                        _search = new BackgroundSearch(_textView.TextSnapshot, _highlight, matchWholeWord,
                                                       delegate
                        {
                            //Force the invalidate to happen on the UI thread to satisfy WPF
                            this.Dispatcher.Invoke(DispatcherPriority.Normal,
                                                   new DispatcherOperationCallback(delegate
                            {
                                //Guard against the view closing before dispatcher executes this.
                                if (!_isDisposed)
                                {
                                    this.InvalidateVisual();
                                    this.RedrawAdornments();
                                }
                                return(null);
                            }),
                                                   null);
                        });
                    }
                    else
                    {
                        //no highlight == no adornments or marks.
                        _layer.RemoveAllAdornments();
                        this.InvalidateVisual();
                    }

                    return(true);
                }
                else if ((oldHighlight != null) && wereAdornmentsEnabled && this.AdornmentsActive)
                {
                    //The highlight didn't change and isn't null ... therefore both old & new highlight spans have values. Update the adornments so we don't highlight the
                    //match the caret is on.
                    SnapshotSpan translatedOldHighlightSpan = oldHighlightSpan.Value.TranslateTo(_textView.TextSnapshot, SpanTrackingMode.EdgeInclusive);
                    if (translatedOldHighlightSpan != _highlightSpan.Value)
                    {
                        //The spans moved (e.g. the user moved from this on one line to this on another).
                        //Remove the adornment from the new highlight.
                        _layer.RemoveAdornmentsByVisualSpan(_highlightSpan.Value);

                        //Add an adornment at the old source of the highlight span.
                        Geometry g = _textView.TextViewLines.GetMarkerGeometry(translatedOldHighlightSpan);
                        if (g != null)
                        {
                            _layer.AddAdornment(translatedOldHighlightSpan, null, new GeometryAdornment(_adornmentMatchBrush, g));
                        }
                    }
                }
            }

            return(false);
        }
        public async Task <ActionResult <IEnumerable <Background> > > Get([FromQuery] BackgroundSearch backgroundSearch)
        {
            var backgrounds = await _backgroundManager.SearchBackgrounds(backgroundSearch);

            return(Ok(backgrounds));
        }
        /// <summary>
        /// Start a background search for all instances of this.highlight.
        /// </summary>
        private void UpdateMarginMatches(bool force)
        {
            if (((this.matchBrush != null) && this.IsVisible) || (this.adornmentMatchBrush != null))
            {
                SnapshotSpan?oldHighlightSpan = this.highlightSpan;
                string       oldHighlight     = this.highlight;

                this.highlightSpan = BackgroundSearch.GetExtentOfWord(this.textView.Caret.Position.BufferPosition);
                this.highlight     = this.highlightSpan.HasValue ? this.highlightSpan.Value.GetText() : null;

                if ((this.highlight != oldHighlight) || force)
                {
                    //The text of the highlight changes ... restart the search.
                    if (this.search != null)
                    {
                        //Stop and blow away the old search (even if it didn't finish, the results are not interesting anymore).
                        this.search.Abort();
                        this.search = null;
                    }

                    if (this.highlight != null)
                    {
                        //The underlying buffer could be very large, meaning that doing the search for all matches on the UI thread
                        //is a bad idea. Do the search on the background thread and use a callback to invalidate the visual when
                        //the entire search has completed.
                        this.search = new BackgroundSearch(this.textView.TextSnapshot, this.highlight,
                                                           delegate
                        {
                            //Force the invalidate to happen on the UI thread to satisfy WPF
                            this.Dispatcher.Invoke(DispatcherPriority.Normal,
                                                   new DispatcherOperationCallback(delegate
                            {
                                this.InvalidateVisual();
                                this.RedrawAdornments(null);
                                return(null);
                            }),
                                                   null);
                        });
                    }
                    else
                    {
                        //no highlight == no adornments or marks.
                        this.layer.RemoveAllAdornments();
                        this.InvalidateVisual();
                    }
                }
                else if (oldHighlight != null)
                {
                    //The highlight didn't change and isn't null ... therefore both old & new highlight spans have values.
                    SnapshotSpan translatedOldHighlightSpan = oldHighlightSpan.Value.TranslateTo(this.textView.TextSnapshot, SpanTrackingMode.EdgeInclusive);
                    if (translatedOldHighlightSpan != this.highlightSpan.Value)
                    {
                        if (this.adornmentMatchBrush != null)
                        {
                            //The spans moved (e.g. the user moved from this on one line to this on another).
                            //Remove the adornment from the new highlight.
                            this.layer.RemoveAdornmentsByVisualSpan(this.highlightSpan.Value);

                            //Add an adornment at the old source of the highlight span.
                            Geometry g = this.textView.TextViewLines.GetMarkerGeometry(translatedOldHighlightSpan);
                            if (g != null)
                            {
                                this.layer.AddAdornment(translatedOldHighlightSpan, null, new GeometryAdornment(this.adornmentMatchBrush, g));
                            }
                        }

                        //We also need to update the caret position in the margin.
                        this.InvalidateVisual();
                    }
                }
            }
            else if (this.IsVisible && (this.caretBrush != null))
            {
                //Neither the match brush nor the adornment brush exists so we won't be doing a background search.
                //But we are visible and the caret brush exists, so invalidate the visual so that we can update the location of the caret.
                this.InvalidateVisual();
            }
        }