添加项目文件。
This commit is contained in:
265
Szmedi.RvKits/RvScript/DocumentViewModel.cs
Normal file
265
Szmedi.RvKits/RvScript/DocumentViewModel.cs
Normal file
@@ -0,0 +1,265 @@
|
||||
using ICSharpCode.AvalonEdit.Document;
|
||||
using ICSharpCode.AvalonEdit.Utils;
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Formatting;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
|
||||
using TextDocument = ICSharpCode.AvalonEdit.Document.TextDocument;
|
||||
|
||||
namespace Szmedi.RvKits.RvScript
|
||||
{
|
||||
/// <summary>
|
||||
/// 每个脚本文件视图的ViewModel
|
||||
/// </summary>
|
||||
public partial class DocumentViewModel : ObservableObject /*ObservableRecipient, IRecipient<string>*/
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool _isReadOnly;
|
||||
|
||||
RoslynEditorViewModel RoslynEditorViewModel { get; }
|
||||
|
||||
public DocumentViewModel(RoslynEditorViewModel roslynEditorViewModel, string FilePath)
|
||||
{
|
||||
RoslynEditorViewModel = roslynEditorViewModel;
|
||||
this.FilePath = FilePath;
|
||||
Title = FileName;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
public DocumentViewModel(RoslynEditorViewModel roslynEditorViewModel)
|
||||
{
|
||||
//WeakReferenceMessenger.Default.Register<DocumentViewModel, string, string>(this, "RunScript", (r, m) => r.Receive(m));
|
||||
RoslynEditorViewModel = roslynEditorViewModel;
|
||||
IsDirty = true;
|
||||
Title = FileName;
|
||||
}
|
||||
|
||||
internal void Initialize(DocumentId id)
|
||||
{
|
||||
Id = id;
|
||||
|
||||
if (Document != null && Document.TextLength > 0)
|
||||
{
|
||||
var doc = RoslynEditorViewModel.Host.GetDocument(id);
|
||||
if (doc != null)
|
||||
{
|
||||
RoslynEditorViewModel.Host.UpdateDocument(doc.WithText(SourceText.From(Document.Text)));
|
||||
IsDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnTextChanged(object sender, EventArgs e)
|
||||
{
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
public DocumentId Id { get; private set; }
|
||||
|
||||
[ObservableProperty]
|
||||
private TextDocument _document = null;
|
||||
|
||||
[ObservableProperty]
|
||||
private string title = null;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(FileName))]
|
||||
[NotifyPropertyChangedFor(nameof(Title))]
|
||||
private bool isDirty = false;
|
||||
|
||||
|
||||
private string _isReadOnlyReason = string.Empty;
|
||||
public string IsReadOnlyReason
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isReadOnlyReason;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
SetProperty(ref _isReadOnlyReason, value);
|
||||
}
|
||||
}
|
||||
private string _filePath = null;
|
||||
public string FilePath
|
||||
{
|
||||
get { return _filePath; }
|
||||
set
|
||||
{
|
||||
if (_filePath != value)
|
||||
{
|
||||
_filePath = value;
|
||||
|
||||
OnPropertyChanged(nameof(FilePath));
|
||||
OnPropertyChanged(nameof(FileName));
|
||||
OnPropertyChanged(nameof(Title));
|
||||
|
||||
if (File.Exists(_filePath))
|
||||
{
|
||||
Document = new TextDocument();
|
||||
IsDirty = false;
|
||||
IsReadOnly = false;
|
||||
|
||||
// Check file attributes and set to read-only if file attributes indicate that
|
||||
if ((File.GetAttributes(_filePath) & FileAttributes.ReadOnly) != 0)
|
||||
{
|
||||
IsReadOnly = true;
|
||||
IsReadOnlyReason = "无法编辑该文件,另一个进程正在写入\n" +
|
||||
"如果你想编辑它,请修改访问许可或另存文件到其他位置。";
|
||||
}
|
||||
|
||||
using (FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
using (StreamReader reader = FileReader.OpenStream(fs, System.Text.Encoding.UTF8))
|
||||
{
|
||||
Document = new TextDocument(reader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
|
||||
ContentId = _filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (FilePath == null)
|
||||
return "未命名脚本" + (IsDirty ? "*" : "");
|
||||
|
||||
return Path.GetFileName(FilePath) + (IsDirty ? "*" : "");
|
||||
}
|
||||
}
|
||||
[ObservableProperty]
|
||||
private string _contentId = null;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isActive = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isSelected = false;
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public bool HasError { get; private set; }
|
||||
|
||||
//private static MethodInfo HasSubmissionResult { get; } =
|
||||
// typeof(Compilation).GetMethod(nameof(HasSubmissionResult), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
|
||||
|
||||
[RelayCommand(CanExecute = nameof(IsDirty))]
|
||||
private void Save()
|
||||
{
|
||||
Text = GetCode();
|
||||
RoslynEditorViewModel.Save(this, false);
|
||||
}
|
||||
|
||||
private string GetCode()
|
||||
{
|
||||
var document = RoslynEditorViewModel.Host.GetDocument(Id);
|
||||
if (document == null)
|
||||
return string.Empty;
|
||||
return document.GetTextAsync()?.Result.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[RelayCommand(CanExecute = nameof(IsDirty))]
|
||||
private void SaveAs()
|
||||
{
|
||||
Text = GetCode();
|
||||
RoslynEditorViewModel.Save(this, true);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Close()
|
||||
{
|
||||
RoslynEditorViewModel.Close(this);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Run()
|
||||
{
|
||||
|
||||
Text = GetCode();
|
||||
RoslynEditorViewModel.Run(this);
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void Format()
|
||||
{
|
||||
var document = RoslynEditorViewModel.Host.GetDocument(Id);
|
||||
var formattedDocument = Formatter.FormatAsync(document).Result;
|
||||
RoslynEditorViewModel.Host.UpdateDocument(formattedDocument);
|
||||
}
|
||||
[RelayCommand]
|
||||
private void Comment()
|
||||
{
|
||||
|
||||
if (RoslynEditorViewModel.CodeEditor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var roslynEditor = RoslynEditorViewModel.CodeEditor;
|
||||
var document = roslynEditor.Document;
|
||||
var startLine = document.GetLineByOffset(roslynEditor.SelectionStart);
|
||||
var endLine = document.GetLineByOffset(roslynEditor.SelectionStart + roslynEditor.SelectionLength);
|
||||
|
||||
document.BeginUpdate();
|
||||
var line = startLine;
|
||||
while (line != null && line.LineNumber <= endLine.LineNumber)
|
||||
{
|
||||
var whitespace = TextUtilities.GetLeadingWhitespace(document, line);
|
||||
if (line.Length > whitespace.Length)
|
||||
{
|
||||
var text = document.GetText(whitespace) + "//";
|
||||
document.Replace(whitespace.Offset, whitespace.Length, text, OffsetChangeMappingType.RemoveAndInsert);
|
||||
}
|
||||
line = line.NextLine;
|
||||
}
|
||||
document.EndUpdate();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void UnComment()
|
||||
{
|
||||
if (RoslynEditorViewModel.CodeEditor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var roslynEditor = RoslynEditorViewModel.CodeEditor;
|
||||
|
||||
var document = roslynEditor.Document;
|
||||
var startLine = document.GetLineByOffset(roslynEditor.SelectionStart);
|
||||
var endLine = document.GetLineByOffset(roslynEditor.SelectionStart + roslynEditor.SelectionLength);
|
||||
|
||||
document.BeginUpdate();
|
||||
var line = startLine;
|
||||
while (line != null && line.LineNumber <= endLine.LineNumber)
|
||||
{
|
||||
var whitespace = TextUtilities.GetLeadingWhitespace(document, line);
|
||||
if (line.Length > whitespace.Length + 2)
|
||||
{
|
||||
var text = document.GetText(whitespace.EndOffset, 2);
|
||||
if (text == "//")
|
||||
document.Remove(whitespace.EndOffset, 2);
|
||||
}
|
||||
line = line.NextLine;
|
||||
}
|
||||
document.EndUpdate();
|
||||
}
|
||||
|
||||
//public void Receive(string message)
|
||||
//{
|
||||
// this.Text = message;
|
||||
//}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user