bool ISelectionManager.SelectWordBoundaries(CursorPosition pos) { var dmsg = screenBuffer.Messages[pos.DisplayIndex]; var word = wordSelection.FindWordBoundaries( GetTextToDisplay(dmsg.Message).GetNthTextLine(dmsg.TextLineIndex), pos.LineCharIndex); if (word != null) { SetSelection(pos.DisplayIndex, SelectionFlag.NoHScrollToSelection, word.Item1); SetSelection(pos.DisplayIndex, SelectionFlag.PreserveSelectionEnd, word.Item2); return(true); } return(false); }
public bool Contains(CursorPosition pos) { if (pos == null) { throw new ArgumentNullException(); } if (IsEmpty) { return(false); } var normalized = this.Normalize(); return(CursorPosition.Compare(normalized.First, pos) <= 0 && CursorPosition.Compare(normalized.Last, pos) >= 0); }
async Task <List <ScreenBufferEntry> > GetSelectedDisplayMessagesEntries() { var viewLines = screenBuffer.Messages; Func <CursorPosition, bool> isGoodDisplayPosition = p => { if (p.Message == null) { return(true); } return(p.DisplayIndex >= 0 && p.DisplayIndex < viewLines.Count); }; var normSelection = selection.Normalize(); if (normSelection.IsEmpty) { return(new List <ScreenBufferEntry>()); } Func <List <ScreenBufferEntry> > defaultGet = () => { int selectedLinesCount = normSelection.Last.DisplayIndex - normSelection.First.DisplayIndex + 1; return(viewLines.Skip(normSelection.First.DisplayIndex).Take(selectedLinesCount).ToList()); }; if (isGoodDisplayPosition(normSelection.First) && isGoodDisplayPosition(normSelection.Last)) { // most common case: both positions are in the screen buffer at the moment return(defaultGet()); } CancellationToken cancellation = CancellationToken.None; IScreenBuffer tmpBuf = screenBufferFactory.CreateScreenBuffer(initialBufferPosition: InitialBufferPosition.Nowhere); await tmpBuf.SetSources(screenBuffer.Sources.Select(s => s.Source), cancellation); if (!await tmpBuf.MoveToBookmark(bookmarksFactory.CreateBookmark(normSelection.First.Message, 0), BookmarkLookupMode.ExactMatch, cancellation)) { // Impossible to load selected message into screen buffer. Rather impossible. return(defaultGet()); } var tasks = screenBuffer.Sources.Select(async sourceBuf => { var sourceMessages = new List <IMessage>(); await sourceBuf.Source.EnumMessages( tmpBuf.Sources.First(sb => sb.Source == sourceBuf.Source).Begin, m => { if (MessagesComparer.Compare(m, normSelection.Last.Message) > 0) { return(false); } sourceMessages.Add(m); return(true); }, EnumMessagesFlag.Forward, LogProviderCommandPriority.AsyncUserAction, cancellation ); return(new { Source = sourceBuf.Source, Messages = sourceMessages }); }).ToList(); await Task.WhenAll(tasks); cancellation.ThrowIfCancellationRequested(); var messagesToSource = tasks.ToDictionary( t => (IMessagesCollection) new MessagesContainers.SimpleCollection(t.Result.Messages), t => t.Result.Source); return (new MessagesContainers.SimpleMergingCollection(messagesToSource.Keys) .Forward(0, int.MaxValue) .SelectMany(m => Enumerable.Range(0, GetTextToDisplay(m.Message.Message).GetLinesCount()).Select( lineIdx => new ScreenBufferEntry() { TextLineIndex = lineIdx, Message = m.Message.Message, Source = messagesToSource[m.SourceCollection], } ) ) .TakeWhile(m => CursorPosition.Compare(CursorPosition.FromViewLine(m.ToViewLine(), 0), normSelection.Last) <= 0) .ToList()); }
bool BelongsToNonExistentSource(CursorPosition pos) { return(pos.Message != null && !screenBuffer.ContainsSource(pos.Source)); }
void SetSelection(int displayIndex, SelectionFlag flag = SelectionFlag.None, int?textCharIndex = null) { var dmsg = screenBuffer.Messages[displayIndex]; var msg = dmsg.Message; var line = GetTextToDisplay(msg).GetNthTextLine(dmsg.TextLineIndex); int newLineCharIndex; if ((flag & SelectionFlag.SelectBeginningOfLine) != 0) { newLineCharIndex = 0; } else if ((flag & SelectionFlag.SelectEndOfLine) != 0) { newLineCharIndex = line.Length; } else { newLineCharIndex = RangeUtils.PutInRange(0, line.Length, textCharIndex.GetValueOrDefault(selection.First.LineCharIndex)); if ((flag & SelectionFlag.SelectBeginningOfNextWord) != 0) { newLineCharIndex = StringUtils.FindNextWordInString(line, newLineCharIndex); } else if ((flag & SelectionFlag.SelectBeginningOfPrevWord) != 0) { newLineCharIndex = StringUtils.FindPrevWordInString(line, newLineCharIndex); } } tracer.Info("Selecting line {0}. Display position = {1}", msg.GetHashCode(), displayIndex); bool resetEnd = (flag & SelectionFlag.PreserveSelectionEnd) == 0; Action doScrolling = () => { if (displayIndex == 0 && screenBuffer.TopLineScrollValue > 1e3) { screenBuffer.TopLineScrollValue = 0; view.Invalidate(); } if ((flag & SelectionFlag.NoHScrollToSelection) == 0) { view.HScrollToSelectedText(selection); } view.RestartCursorBlinking(); }; if (selection.First.Message != msg || selection.First.DisplayIndex != displayIndex || selection.First.LineCharIndex != newLineCharIndex || resetEnd != selection.IsEmpty) { var oldSelection = selection; InvalidateTextLineUnderCursor(); var tmp = new CursorPosition() { Message = msg, Source = dmsg.Source, DisplayIndex = displayIndex, TextLineIndex = dmsg.TextLineIndex, LineCharIndex = newLineCharIndex }; SetSelection(tmp, resetEnd ? tmp : new CursorPosition?()); OnSelectionChanged(); foreach (var displayIndexToInvalidate in oldSelection.GetDisplayIndexesRange().SymmetricDifference(selection.GetDisplayIndexesRange()) .Where(idx => idx < screenBuffer.Messages.Count && idx >= 0)) { view.InvalidateLine(screenBuffer.Messages[displayIndexToInvalidate].ToViewLine()); } InvalidateTextLineUnderCursor(); doScrolling(); UpdateSelectionInplaceHighlightingFields(); if (selection.First.Message != oldSelection.First.Message) { tracer.Info("focused message changed"); OnFocusedMessageChanged(); OnFocusedMessageBookmarkChanged(); } else if (selection.First.TextLineIndex != oldSelection.First.TextLineIndex) { tracer.Info("focused message's line changed"); OnFocusedMessageBookmarkChanged(); } } else if ((flag & SelectionFlag.ScrollToViewEventIfSelectionDidNotChange) != 0) { doScrolling(); } }
public SelectionInfo(CursorPosition first, CursorPosition last, MessageTextGetter messageTextGetter) { this.first = first ?? throw new ArgumentNullException(nameof(first)); this.last = last; this.messageTextGetter = messageTextGetter; }