Dnspy/dnSpy/dnSpy/Output/OutputBufferVM.cs
2021-09-20 18:20:01 +02:00

154 lines
4.7 KiB
C#

/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Windows;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.Output;
using dnSpy.Contracts.Text;
using dnSpy.Contracts.Text.Editor;
using dnSpy.Properties;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Operations;
namespace dnSpy.Output {
sealed class OutputBufferVM : ViewModelBase, IOutputTextPane {
public IInputElement? FocusedElement => logEditor.FocusedElement;
public object? TextEditorUIObject => logEditor.UIObject;
public double ZoomLevel => logEditor.TextView.ZoomLevel;
public Guid Guid { get; }
public string Name { get; }
public int Index {
get => index;
set {
if (index != value) {
index = value;
OnPropertyChanged(nameof(KeyboardShortcut));
}
}
}
int index;
public string KeyboardShortcut {
get {
if ((uint)index >= 10)
return string.Empty;
// Ctrl+0 is bound to reset-zoom, so won't work.
if (index == 9)
return string.Empty;
return "(" + string.Format(dnSpy_Resources.ShortCutKeyCtrlDIGIT, (index + 1) % 10) + ")";
}
}
public WordWrapStyles WordWrapStyle {
get => logEditor.WordWrapStyle;
set => logEditor.WordWrapStyle = value;
}
public bool ShowLineNumbers {
get => logEditor.ShowLineNumbers;
set => logEditor.ShowLineNumbers = value;
}
bool ShowTimestamps => logEditor.TextView.Options.GetOptionValue(DefaultOutputOptions.ShowTimestampsId);
string TimestampDateTimeFormat => logEditor.TextView.Options.GetOptionValue(DefaultOutputOptions.TimestampDateTimeFormatId);
readonly ILogEditor logEditor;
readonly IEditorOperations editorOperations;
public OutputBufferVM(IEditorOperationsFactoryService editorOperationsFactoryService, Guid guid, string name, ILogEditor logEditor) {
editorOperations = editorOperationsFactoryService.GetEditorOperations(logEditor.TextView);
Guid = guid;
Name = name;
this.logEditor = logEditor;
index = -1;
needTimestamp = true;
}
public bool CanCopy {
get {
if (!logEditor.TextView.Selection.IsEmpty)
return true;
var line = logEditor.TextView.Caret.Position.BufferPosition.GetContainingLine();
bool cutEmptyLines = logEditor.TextView.Options.GetOptionValue(DefaultTextViewOptions.CutOrCopyBlankLineIfNoSelectionId);
return cutEmptyLines || !string.IsNullOrWhiteSpace(line.GetText());
}
}
public void Copy() => editorOperations.CopySelection();
public void Clear() {
logEditor.Clear();
needTimestamp = true;
}
bool needTimestamp;
public string GetText() => logEditor.GetText();
public ICachedWriter CreateWriter() => new CachedWriter(this);
public void Write(object color, string? s) => WriteInternal(color, s);
public void Write(TextColor color, string? s) => WriteInternal(color.Box(), s);
public void WriteLine(TextColor color, string? s) => WriteLine(color.Box(), s);
public void WriteLine(object color, string? s) {
WriteInternal(color, s);
WriteInternal(BoxedTextColor.Text, Environment.NewLine);
}
public void Write(IEnumerable<ColorAndText> text) {
foreach (var t in text)
WriteInternal(t.Color, t.Text);
}
void WriteInternal(object color, string? text) {
if (text is null)
return;
int so = 0;
while (so < text.Length) {
if (needTimestamp) {
needTimestamp = false;
if (ShowTimestamps) {
var format = TimestampDateTimeFormat;
if (!string.IsNullOrWhiteSpace(format)) {
logEditor.Write(DateTime.Now.ToString(format), BoxedTextColor.DebugLogTimestamp);
logEditor.Write(" ", BoxedTextColor.Text);
}
}
}
int nlOffs = text.IndexOfAny(LineConstants.newLineChars, so);
if (nlOffs >= 0) {
int nlLen = text[nlOffs] == '\r' && nlOffs + 1 < text.Length && text[nlOffs + 1] == '\n' ? 2 : 1;
int soNext = nlOffs + nlLen;
logEditor.Write(text.Substring(so, soNext - so), color);
so = soNext;
needTimestamp = true;
}
else {
logEditor.Write(so == 0 ? text : text.Substring(so, text.Length - so), color);
break;
}
}
}
}
}