279 lines
8.6 KiB
C#
279 lines
8.6 KiB
C#
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
|
|
using Autodesk.Revit.UI;
|
|
|
|
using AvalonDock;
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
|
|
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.AIScriptRunner.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;
|
|
//}
|
|
}
|
|
}
|