IEnumerable<LogLineMatch> IReadOnlyDictionary<LogLineIndex, IEnumerable<LogLineMatch>>.this[LogLineIndex key] { get { IEnumerable<LogLineMatch> value; TryGetValue(key, out value); return value; } }
public DataSource() { Order = -1; _activatedQuickFilters = new List<Guid>(); LevelFilter = LevelFlags.All; ColorByLevel = true; ShowLineNumbers = true; SelectedLogLines = new HashSet<LogLineIndex>(); VisibleLogLine = LogLineIndex.Invalid; }
public bool TryGetValue(LogLineIndex key, out IEnumerable <LogLineMatch> value) { List <LogLineMatch> values; if (_matches.TryGetValue(key, out values)) { value = values; return(true); } value = Enumerable.Empty <LogLineMatch>(); return(false); }
public DataSource() { Order = -1; _activatedQuickFilters = new List <QuickFilterId>(); LevelFilter = LevelFlags.All; ColorByLevel = true; ShowLineNumbers = true; IsExpanded = true; SelectedLogLines = new HashSet <LogLineIndex>(); VisibleLogLine = LogLineIndex.Invalid; }
private void GoToLineOnLineNumberChosen(LogLineIndex logLineIndex) { Log.DebugFormat("Going to line {0}", logLineIndex); var dataSourceViewModel = _currentDataSourceLogView.DataSource; var dataSource = dataSourceViewModel.DataSource; var logFile = dataSource.FilteredLogFile; var originalIndex = logFile.GetLogLineIndexOfOriginalLineIndex(logLineIndex); dataSourceViewModel.SelectedLogLines = new HashSet <LogLineIndex> { originalIndex }; dataSourceViewModel.RequestBringIntoView(originalIndex); }
public void Append(LogLineIndex index, int count) { if (count <= 0) { return; } if (TryGetLast(out var lastSection)) { if (lastSection.IsInvalidate) { var gap = index - lastSection.Index; if (gap >= 0) { _changes.Add(new LogFileSection(lastSection.Index, count + gap)); } else { throw new NotImplementedException(); } } else if (lastSection.IsReset) { throw new NotImplementedException(); } else { var gap = index - (lastSection.LastIndex + 1); if (gap > 0) { Log.WarnFormat("Inconsistency detected: Last change affects from '{0}' to '{1}' and the next one would leave a gap because it starts at '{2}'!", lastSection.Index, lastSection.LastIndex, index); } else if (gap < 0) { Log.WarnFormat("Inconsistency detected: Last change affects from '{0}' to '{1}' and the next one would overlap because it starts at '{2}'!", lastSection.Index, lastSection.LastIndex, index); } _changes[_changes.Count - 1] = new LogFileSection(lastSection.Index, lastSection.Count + gap + count); } } else { _changes.Add(new LogFileSection(index, count)); } var last = _changes[_changes.Count - 1]; _count = (int)(last.Index + last.Count); }
private void Invalidate(LogFileSection sectionToInvalidate) { var firstInvalidIndex = LogLineIndex.Min(_fullSourceSection.LastIndex, sectionToInvalidate.Index); var lastInvalidIndex = LogLineIndex.Min(_fullSourceSection.LastIndex, sectionToInvalidate.LastIndex); var invalidateCount = lastInvalidIndex - firstInvalidIndex + 1; var previousSourceIndex = _currentSourceIndex; _fullSourceSection = new LogFileSection(0, (int)firstInvalidIndex); if (_fullSourceSection.Count > 0) { // It's possible (likely) that we've received an invalidation for a region of the source // that we've already processed (i.e. created indices for). If that's the case, then we need // to rewind the index. Otherwise nothing needs to be done... var newIndex = _fullSourceSection.LastIndex + 1; if (newIndex < _currentSourceIndex) { _currentSourceIndex = newIndex; } } else { _currentSourceIndex = 0; } lock (_syncRoot) { var toRemove = _indices.Count - lastInvalidIndex; if (toRemove > 0) { _indices.RemoveRange((int)firstInvalidIndex, toRemove); _currentLogEntry = new LogEntryInfo(firstInvalidIndex - 1, 0); } if (previousSourceIndex != _currentSourceIndex) { _indices.RemoveRange((int)_currentSourceIndex, _indices.Count - _currentSourceIndex); } } if (_indices.Count != _currentSourceIndex) { Log.ErrorFormat("Inconsistency detected: We have {0} indices for {1} lines", _indices.Count, _currentSourceIndex); } Listeners.Invalidate((int)firstInvalidIndex, invalidateCount); if (_fullSourceSection.Count > firstInvalidIndex) { _fullSourceSection = new LogFileSection(0, firstInvalidIndex.Value); } }
public bool NavigateTo(DataSourceId dataSource, LogLineIndex line) { if (MainWindow == null) { return(false); } if (LogViewer == null) { return(false); } return(LogViewer.RequestBringIntoView(dataSource, line)); }
private void OnMouseMove(Point relativePos) { double y = relativePos.Y - _yOffset; var visibleLineIndex = (int)Math.Floor(y / _textSettings.LineHeight); if (visibleLineIndex >= 0 && visibleLineIndex < _visibleTextLines.Count) { var lineIndex = new LogLineIndex(_visibleTextLines[visibleLineIndex].LogLine.LineIndex); if (SetHovered(lineIndex, SelectMode.Replace)) { InvalidateVisual(); } } }
public void TestGetEntries2() { _logFile.Setup(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogEntries>(), It.IsAny <int>())).Throws <SystemException>(); var indices = new LogLineIndex[] { 1, 2, 3 }; var buffer = new Mock <ILogEntries>().Object; new Action(() => _proxy.GetEntries(indices, buffer, 101)).Should().NotThrow(); _logFile.Verify(x => x.GetEntries(It.Is <IReadOnlyList <LogLineIndex> >(y => y == indices), It.Is <ILogEntries>(y => ReferenceEquals(y, buffer)), It.Is <int>(y => y == 101)), Times.Once); }
public void Add(int sourceIndex, int count, IReadOnlyLogBuffer source, LogLineIndex destinationIndex) { // Let us see where that data lies in this page.. var pageDestinationIndex = destinationIndex - _section.Index; foreach (var column in _copiedColumns) { _buffer.CopyFrom(column, pageDestinationIndex, source, new Int32Range(sourceIndex, count)); } // We neither need, nor want the source buffer to have to supply the indices - we know them ourselves _buffer.CopyFrom(Columns.Index, pageDestinationIndex, new LogSourceSection(_section.Index + pageDestinationIndex, count), 0, count); _buffer.Fill(PageBufferedLogSource.RetrievalState, RetrievalState.Retrieved, pageDestinationIndex, count); }
public void TestGetEntriesByIndices() { var logFile = new MultiLineLogFile(_taskScheduler, _source.Object, TimeSpan.Zero); var indices = new LogLineIndex[] { 0, 2, 5 }; var buffer = new LogEntryBuffer(3, LogFileColumns.DeltaTime, LogFileColumns.Timestamp); var destinationIndex = 2; logFile.GetEntries(indices, buffer, destinationIndex); _source.Verify(x => x.GetEntries(It.Is <IReadOnlyList <LogLineIndex> >(y => y == indices), It.Is <ILogEntries>(y => y == buffer), It.Is <int>(y => y == destinationIndex)), Times.Once); }
public bool SetSelected(LogLineIndex index, SelectMode selectMode) { bool changed = Set(_selectedIndices, index, selectMode); _firstSelection = _lastSelection = index; if (changed) { var fn = OnSelectionChanged; fn?.Invoke(_selectedIndices); } return(changed); }
/// <inheritdoc /> protected override void DisposeAdditional() { _source.RemoveListener(this); _pendingModifications.Clear(); // https://github.com/Kittyfisto/Tailviewer/issues/282 lock (_syncRoot) { _indices.Clear(); _indices.Capacity = 0; _currentSourceIndex = 0; } _properties.Clear(); }
public bool NavigateTo(LogLineIndex line) { if (MainWindow == null) { return(false); } if (LogViewer == null) { return(false); } MainWindow.SelectRawEntry(); return(LogViewer.RequestBringIntoView(line)); }
/// <inheritdoc /> public override LogLineIndex GetLogLineIndexOfOriginalLineIndex(LogLineIndex originalSourceIndex) { lock (_indices) { for (int i = 0; i < _indices.Count; ++i) { if (_indices[i] == originalSourceIndex.Value) { return(i); } } } return(LogLineIndex.Invalid); }
public void TestGetColumn2() { _logFile.Setup(x => x.GetColumn(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogFileColumn <string> >(), It.IsAny <string[]>(), It.IsAny <int>())).Throws <SystemException>(); var indices = new LogLineIndex[] { 1, 2, 3 }; var buffer = new string[201]; new Action(() => _proxy.GetColumn(indices, LogFileColumns.RawContent, buffer, 101)).Should().NotThrow(); _logFile.Verify(x => x.GetColumn(It.Is <IReadOnlyList <LogLineIndex> >(y => y == indices), It.Is <ILogFileColumn <string> >(y => Equals(y, LogFileColumns.RawContent)), It.Is <string[]>(y => ReferenceEquals(y, buffer)), It.Is <int>(y => y == 101)), Times.Once); }
private void OnMoveDown() { try { if (_selectedIndices.Count > 0 && _lastSelection < _logSource.GetProperty(Properties.LogEntryCount) - 1) { LogLineIndex newIndex = _lastSelection + 1; ChangeSelectionAndBringIntoView(newIndex); } } catch (Exception e) { Log.ErrorFormat("Caught unexpected exception: {0}", e); } }
private void RemoveRange(LogFileSection section) { var previousLine = section.Index > 0 ? _lines[(int)section.Index] : new LogLine(-1, -1, null, LevelFlags.None); for (int i = 0; i < section.Count; ++i) { LogLineIndex index = section.Index + i; LogLine line = _lines[(int)index]; DecrementCount(line, previousLine); previousLine = line; } _lines.RemoveRange((int)section.Index, section.Count); }
public bool Contains(ILogFile logFile, LogLineIndex index) { if (logFile == null) { return(false); } if (index == LogLineIndex.Invalid) { return(false); } lock (_syncRoot) { return(_logLines.Contains(logFile, index)); } }
public Task <LogLineResponse> RequestAsync(LogFileSection section, CancellationToken cancellationToken) { // We have all the indices in memory and thus we can retrieve the // list of original indices immediately because it's a very inexpensive operation. var originalIndices = new LogLineIndex[section.Count]; var tasks = new Task <LogLineResponse> [section.Count]; lock (_syncRoot) { // !!!! DON'T GIVE CONTROL TO ANYONE ELSE INSIDE THIS LOCK !!!! for (int i = 0; i < section.Count; ++i) { var filteredIndex = section.Index + i; var originalIndex = _indices[filteredIndex.Value]; originalIndices[i] = originalIndex; } } for (int i = 0; i < section.Count; ++i) { tasks[i] = _source.RequestAsync(new LogFileSection(originalIndices[i], 1), cancellationToken); } return(Task.WhenAll(tasks).ContinueWith(unused => { var lines = new LogLine[section.Count]; // The caller may have requested a (partially) invalid section, for example because those parts // of the log file have been removed (due to filtering, etc...). It is for this reason that // we allow partial responses which consists of the first N successful responses. int actualCount; for (actualCount = 0; actualCount < section.Count && !tasks[actualCount].IsCanceled && !tasks[actualCount].IsFaulted; ++actualCount) { var task = tasks[actualCount]; if (task.IsCompleted) { var result = tasks[actualCount].Result; lines[actualCount] = result.Lines[0]; } } var responses = new LogLineResponse { Lines = lines, ActualSection = new LogFileSection(section.Index, actualCount) }; return responses; }, cancellationToken)); }
public void TestConstruction9() { var lineIndex = new LogLineIndex(1); var entryIndex = new LogEntryIndex(42); var sourceId = new LogLineSourceId(254); var t = new DateTime(2017, 11, 26, 12, 20, 1); var line = new LogLine(lineIndex, entryIndex, sourceId, "Hello, World!", LevelFlags.Trace, t); line.LineIndex.Should().Be(1); line.OriginalLineIndex.Should().Be(1); line.LogEntryIndex.Should().Be(42); line.SourceId.Should().Be(sourceId); line.Message.Should().Be("Hello, World!"); line.Level.Should().Be(LevelFlags.Trace); line.Timestamp.Should().Be(t); line.MatchedFilters.Should().Be(0); }
public void Restore(XmlReader reader) { for (var i = 0; i < reader.AttributeCount; ++i) { reader.MoveToAttribute(i); switch (reader.Name) { case "datasource": DataSourceId = new DataSourceId(reader.ReadContentAsGuid()); break; case "index": Index = reader.ReadContentAsInt(); break; } } }
public void TestGetEntries2() { _logFile.Setup(x => x.GetEntries(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <ILogBuffer>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>())).Throws <SystemException>(); var indices = new LogLineIndex[] { 1, 2, 3 }; var buffer = new Mock <ILogBuffer>().Object; var destinationIndex = 101; var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache); new Action(() => _proxy.GetEntries(indices, buffer, destinationIndex, queryOptions)).Should().NotThrow(); _logFile.Verify(x => x.GetEntries(It.Is <IReadOnlyList <LogLineIndex> >(y => y == indices), It.Is <ILogBuffer>(y => ReferenceEquals(y, buffer)), destinationIndex, queryOptions), Times.Once); }
private void OnCurrentLineChanged(LogLineIndex index) { var current = PartTextCanvas.CurrentlyVisibleSection; if (index != LogLineIndex.Invalid) { PartTextCanvas.CurrentLine = (int)index; //< We don't want to call BringIntoView() everytime because that one scrolls to fully // bring a line into view. This would mean that if the currently visible section changed // so that the top line is only partially visible, then this method would always bring // it fully visible. Removing the following filter would completely remove per pixel scrolling... if (current.Index != index) { _verticalScrollBar.Value = (int)index * TextHelper.LineHeight; } } }
public void TestGetColumn2() { _logFile.Setup(x => x.GetColumn(It.IsAny <IReadOnlyList <LogLineIndex> >(), It.IsAny <IColumnDescriptor <string> >(), It.IsAny <string[]>(), It.IsAny <int>(), It.IsAny <LogSourceQueryOptions>())).Throws <SystemException>(); var indices = new LogLineIndex[] { 1, 2, 3 }; var buffer = new string[201]; var queryOptions = new LogSourceQueryOptions(LogSourceQueryMode.FromCache); new Action(() => _proxy.GetColumn(indices, Columns.RawContent, buffer, 101, queryOptions)).Should().NotThrow(); _logFile.Verify(x => x.GetColumn(It.Is <IReadOnlyList <LogLineIndex> >(y => y == indices), It.Is <IColumnDescriptor <string> >(y => Equals(y, Columns.RawContent)), It.Is <string[]>(y => ReferenceEquals(y, buffer)), It.Is <int>(y => y == 101), queryOptions), Times.Once); }
public void RemoveFrom(LogLineIndex firstInvalidIndex) { if (firstInvalidIndex >= _count) { Log.WarnFormat("Ignoring invalidation from index '{0}' onwards because nothing has been appended there!", firstInvalidIndex); return; } if (firstInvalidIndex >= _initialCount) { // We do not need to add an invalidation, rather we can simply clamp an existing previous append if (firstInvalidIndex > 0) { var previous = _modifications[_modifications.Count - 1]; if (previous.IsAppended(out var appendedSection)) { var gap = appendedSection.Index + appendedSection.Count - firstInvalidIndex; if (gap > 0) { appendedSection.Count -= gap; _modifications[_modifications.Count - 1] = LogSourceModification.Appended(appendedSection); } } } } else { var invalidationCount = _count - firstInvalidIndex; if (_removeIndex != -1) { var invalidation = _modifications[_removeIndex]; invalidation.IsRemoved(out var removedSection); if (removedSection.Index <= firstInvalidIndex) { return; //< Nothing to do } _modifications[_removeIndex] = LogSourceModification.Removed(firstInvalidIndex, invalidationCount); } else { _removeIndex = _modifications.Count; _modifications.Add(LogSourceModification.Removed(firstInvalidIndex, invalidationCount)); } } }
public void TestGetOriginalIndexFrom2() { using (var proxy = new LogFileProxy(_scheduler, TimeSpan.Zero, _logFile.Object)) { var buffer = new LogLineIndex[100]; proxy.GetColumn(new LogFileSection(1, 42), LogFileColumns.OriginalIndex, buffer, 47); _logFile.Verify(x => x.GetColumn(It.Is <LogFileSection>(y => y == new LogFileSection(1, 42)), It.Is <ILogFileColumn <LogLineIndex> >(y => y == LogFileColumns.OriginalIndex), It.Is <LogLineIndex[]>(y => y == buffer), It.Is <int>(y => y == 47)), Times.Once, "because the proxy should simply forward those calls to its source"); } }
private bool TryGetEntriesContiguous(LogSourceSection sourceSection, ILogBuffer destination, int destinationIndex, out IReadOnlyList <LogSourceSection> accessedPageBoundaries) { bool fullyRead = true; var sourceSectionEndIndex = Math.Min((int)(sourceSection.Index + sourceSection.Count), _sourceCount); var numEntriesRead = 0; var tmpAccessedPageBoundaries = new List <LogSourceSection>(); for (LogLineIndex i = sourceSection.Index; i < sourceSectionEndIndex;) { var pageIndex = GetPageIndex(i); var remainingPageCount = (pageIndex + 1) * _pageSize - i; var count = Math.Min(remainingPageCount, sourceSectionEndIndex - i); var page = TryGetPage(pageIndex); if (page != null) { fullyRead &= page.TryRead(i, count, destination, destinationIndex + numEntriesRead, fullyRead); tmpAccessedPageBoundaries.Add(page.Section); } else { destination.FillDefault(destinationIndex + numEntriesRead, count); if (destination.Contains(PageBufferedLogSource.RetrievalState)) { destination.Fill(PageBufferedLogSource.RetrievalState, RetrievalState.NotCached, destinationIndex + numEntriesRead, count); } fullyRead = false; tmpAccessedPageBoundaries.Add(GetSectionForPage(pageIndex)); } numEntriesRead += count; i += count; } if (numEntriesRead < sourceSection.Count) { var start = destinationIndex + numEntriesRead; destination.FillDefault(start, sourceSection.Count - numEntriesRead); fullyRead = false; } accessedPageBoundaries = tmpAccessedPageBoundaries; return(fullyRead); }
public void InvalidateFrom(LogLineIndex firstInvalidIndex) { if (firstInvalidIndex >= _count) { Log.WarnFormat("Ignoring invalidation from index '{0}' onwards because nothing has been appended there!", firstInvalidIndex); return; } if (firstInvalidIndex >= _initialCount) { // We do not need to add an invalidation, rather we can simply clamp an existing previous append if (firstInvalidIndex > 0) { var previous = _changes[_changes.Count - 1]; if (!previous.IsInvalidate && !previous.IsReset) { var gap = previous.Index + previous.Count - firstInvalidIndex; if (gap > 0) { previous.Count -= gap; _changes[_changes.Count - 1] = previous; } } } } else { var invalidationCount = _count - firstInvalidIndex; if (_invalidationIndex != -1) { var invalidation = _changes[_invalidationIndex]; if (invalidation.Index <= firstInvalidIndex) { return; //< Nothing to do } _changes[_invalidationIndex] = LogFileSection.Invalidate(firstInvalidIndex, invalidationCount); } else { _invalidationIndex = _changes.Count; _changes.Add(LogFileSection.Invalidate(firstInvalidIndex, invalidationCount)); } } }
private static bool Set(HashSet <LogLineIndex> indices, LogLineIndex index, SelectMode selectMode) { if (selectMode == SelectMode.Replace) { if (indices.Count != 1 || !indices.Contains(index)) { indices.Clear(); indices.Add(index); return(true); } } else if (indices.Add(index)) { return(true); } return(false); }
public MergedLogLineIndex this[LogLineIndex index] { get { if (index.IsInvalid) { return(MergedLogLineIndex.Invalid); } lock (_syncRoot) { if (index >= _indices.Count) { return(MergedLogLineIndex.Invalid); } return(_indices[(int)index]); } } }
public void Add(LogLineIndex index, LogLineMatch match) { Add(new LogMatch(index, match)); }
public void Restore(XmlReader reader, out bool neededPatching) { int count = reader.AttributeCount; for (int i = 0; i < count; ++i) { reader.MoveToAttribute(i); switch (reader.Name) { case "file": File = reader.Value; break; case "followtail": FollowTail = reader.ReadContentAsBool(); break; case "showlinenumbers": ShowLineNumbers = reader.ReadContentAsBool(); break; case "stringfilter": case "searchterm": SearchTerm = reader.Value; break; case "levelfilter": LevelFilter = reader.ReadContentAsEnum<LevelFlags>(); break; case "colorbylevel": ColorByLevel = reader.ReadContentAsBool(); break; case "visibleentryindex": VisibleLogLine = reader.ReadContentAsInt(); break; case "id": Id = reader.ReadContentAsGuid(); break; case "parentid": ParentId = reader.ReadContentAsGuid(); break; case "lastviewed": LastViewed = reader.ReadContentAsDateTime2(); break; case "horizontaloffset": HorizontalOffset = reader.ReadContentAsDouble2(); break; } } if (Id == Guid.Empty) { Id = Guid.NewGuid(); Log.InfoFormat("Data Source '{0}' doesn't have an ID yet, setting it to: {1}", File, Id ); neededPatching = true; } else { neededPatching = false; } reader.MoveToContent(); XmlReader subtree = reader.ReadSubtree(); while (subtree.Read()) { switch (subtree.Name) { case "activatedquickfilters": IEnumerable<Guid> filters = ReadActivatedQuickFilters(reader); ActivatedQuickFilters.Clear(); ActivatedQuickFilters.AddRange(filters); break; } } }
public void Select(LogLineIndex index) { PART_ListView.Select(index); }
internal void OnMoveStart() { try { var newIndex = new LogLineIndex(0); ChangeSelectionAndBringIntoView(newIndex); } catch (Exception e) { Log.ErrorFormat("Caught unexpected exception: {0}", e); } }
public void Select(LogLineIndex index) { _textCanvas.SetSelected(index, SelectMode.Replace); }
private void OnCurrentLineChanged(LogLineIndex index) { LogFileSection current = _textCanvas.CurrentlyVisibleSection; if (index != LogLineIndex.Invalid) { _textCanvas.CurrentLine = (int) index; //< We don't want to call BringIntoView() everytime because that one scrolls to fully // bring a line into view. This would mean that if the currently visible section changed // so that the top line is only partially visible, then this method would always bring // it fully visible. Removing the following filter would completely remove per pixel scrolling... if (current.Index != index) { _verticalScrollBar.Value = (int) index*TextHelper.LineHeight; } } }
private bool SetSelected(LogLineIndex from, LogLineIndex to, SelectMode selectMode) { bool changed = false; if (selectMode == SelectMode.Replace) { if (_hoveredIndices.Count > 0) changed = true; _hoveredIndices.Clear(); } LogLineIndex min = LogLineIndex.Min(from, to); LogLineIndex max = LogLineIndex.Max(from, to); int count = max - min; for (int i = 0; i <= count /* we want to select everything including 'to' */; ++i) { changed |= _selectedIndices.Add(min + i); } if (changed) { var fn = OnSelectionChanged; if (fn != null) fn(_selectedIndices); } return changed; }
private void UpdateMouseOver(Point relativePos) { double y = relativePos.Y - _yOffset; var visibleLineIndex = (int) Math.Floor(y/TextHelper.LineHeight); if (visibleLineIndex >= 0 && visibleLineIndex < _visibleTextLines.Count) { var lineIndex = new LogLineIndex(_visibleTextLines[visibleLineIndex].LogLine.LineIndex); if (SetHovered(lineIndex, SelectMode.Replace)) InvalidateVisual(); } }
private bool SetHovered(LogLineIndex index, SelectMode selectMode) { return Set(_hoveredIndices, index, selectMode); }
private void ChangeSelectionAndBringIntoView(LogLineIndex newIndex) { if (SetSelected(newIndex, SelectMode.Replace)) { Action<LogLineIndex> fn = RequestBringIntoView; if (fn != null) fn(newIndex); InvalidateVisual(); } }
private static bool Set(HashSet<LogLineIndex> indices, LogLineIndex index, SelectMode selectMode) { if (selectMode == SelectMode.Replace) { if (indices.Count != 1 || !indices.Contains(index)) { indices.Clear(); indices.Add(index); return true; } } else if (indices.Add(index)) { return true; } return false; }
public void TestIncrement() { var idx = new LogLineIndex(0); ++idx; idx.Should().Be(new LogLineIndex(1)); }
public bool SetSelected(LogLineIndex index, SelectMode selectMode) { bool changed = Set(_selectedIndices, index, selectMode); _lastSelection = index; if (changed) { var fn = OnSelectionChanged; if (fn != null) fn(_selectedIndices); } return changed; }
private void TextCanvasOnRequestBringIntoView(LogLineIndex logLineIndex) { BringIntoView(logLineIndex); }
public bool ContainsKey(LogLineIndex key) { throw new System.NotImplementedException(); }
private void BringIntoView(LogLineIndex logLineIndex) { double height = _textCanvas.ActualHeight; double offset = _textCanvas.YOffset; int start = _textCanvas.CurrentLine; int diff = logLineIndex - start; double min = ((diff)*TextHelper.LineHeight + offset); double max = ((diff + 1)*TextHelper.LineHeight + offset); if (min < 0) { _verticalScrollBar.Value += min; } else if (max > height) { _verticalScrollBar.Value += (max - height); } ILogFile logFile = LogFile; if (logFile != null) { int count = logFile.Count; if (count > 0) { if (logLineIndex < count - 1) { FollowTail = false; } else { FollowTail = true; } } } }
private void OnCurrentLogLineChanged(LogLineIndex index) { IDataSourceViewModel dataSource = DataSource; if (dataSource != null) { // We most certainly do not want to change the // VIsibleLogLine property of a DataSource while we're switching // out said data source. This is bound to happen because stuff // get's resized etc... if (!_changingLogView) { dataSource.VisibleLogLine = index; } } }
public bool TryGetValue(LogLineIndex key, out IEnumerable<LogLineMatch> value) { List<LogLineMatch> values; if (_matches.TryGetValue(key, out values)) { value = values; return true; } value = Enumerable.Empty<LogLineMatch>(); return false; }
internal void OnMoveEnd() { try { ILogFile logFile = _logFile; if (logFile != null) { var count = logFile.Count; if (count > 0) { var newIndex = new LogLineIndex(count - 1); ChangeSelectionAndBringIntoView(newIndex); } } } catch (Exception e) { Log.ErrorFormat("Caught unexpected exception: {0}", e); } }