Files
2026-11-01 23:39:55 +02:00

261 lines
7.0 KiB
C#

using System;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.UIElements;
using Codice.Client.BaseCommands;
using Codice.CM.Client.Differences.Graphic;
using MergetoolGui;
using Unity.CodeEditor;
using Unity.CodeEditor.Document;
using Unity.CodeEditor.TextMate;
using Unity.PlasticSCM.Editor.Diff;
using Unity.PlasticSCM.Editor.Diff.SyntaxHighlight;
using Unity.PlasticSCM.Editor.Diff.Text;
using XDiffGui;
using XDiffGui.Options;
using Language = XDiffGui.Options.Language;
namespace Unity.PlasticSCM.Editor.Diff.Text
{
internal class TextEditorPanel : VisualElement
{
internal event Action<bool> DirtyStateChanged;
internal bool IsTextDirty { get; private set; }
internal Language CurrentLanguage => mCurrentLanguage;
internal Unity.CodeEditor.TextEditor TextEditor =>
mTextEditor;
internal TextEditorPanel(
ISaveChangesListener saveChangesListener)
{
style.flexGrow = 1;
mTextEditor =
DiffTextViewBuilder.CreateTextEditor();
mTextEditor.Options.AllowScrollBelowDocument =
false;
mTextEditor.HorizontalScrollBarVisibility =
ScrollBarVisibility.Auto;
mTextEditor.VerticalScrollBarVisibility =
ScrollBarVisibility.Auto;
mTextEditor.ShowLineNumbers = true;
mTextMateInstallation =
mTextEditor.InstallTextMate();
mTextEditorContextMenu =
new DiffTextViewContextMenu(mTextEditor);
mTextEditor.TextChanged +=
TextEditor_TextChanged;
mTextEditorSaveKeyBinding =
TextEditorSaveKeyBinding.InitForEditor(
mTextEditor, saveChangesListener);
Add(mTextEditor);
}
internal void ShowFileContent(
string file,
Encoding encoding,
string pathForEdition)
{
mPathForEdition = pathForEdition;
mEncoding = encoding;
long fileSize =
BaseServices.CalcFileSize(file, true);
string content = ContentDataReader.GetContent(
file,
encoding,
pathForEdition,
out bool allowEdit);
Language language =
SyntaxLanguageFactory.GetSyntaxLanguage(
fileSize,
Path.GetExtension(file),
UnitySyntaxLanguages.AdditionalExtensions);
if (allowEdit &&
DraftStorage.TryLoadDraft(
pathForEdition, out string draftContent))
{
ShowContent(draftContent, language, allowEdit);
SetDirtyState(true);
return;
}
ShowContent(content, language, allowEdit);
}
internal void ShowContent(
string content,
Language language,
bool isEditable)
{
if (content == null)
return;
mbIsUpdatingTextBox = true;
try
{
if (language != mCurrentLanguage)
mTextMateInstallation.SetLanguage(
Language.PlainText);
mCurrentLanguage = language;
mTextEditor.Document =
new TextDocument(content);
mTextEditor.IsReadOnly = !isEditable;
mTextMateInstallation.SetLanguage(language);
SetDirtyState(false);
}
finally
{
mbIsUpdatingTextBox = false;
}
}
internal void SetLanguage(Language language)
{
mCurrentLanguage = language;
mTextMateInstallation.SetLanguage(language);
}
internal void SaveChanges(
IAfterSaveChangesListener afterSaveChangesListener)
{
try
{
SaveFileOperations.SaveAs(
mPathForEdition,
mTextEditor.Text,
mEncoding);
}
catch (Exception ex)
{
Debug.LogException(ex);
}
DraftStorage.DeleteDraft(mPathForEdition);
SetDirtyState(false);
afterSaveChangesListener?.AfterSaveChanges(
mPathForEdition);
}
internal void DiscardChanges()
{
DraftStorage.DeleteDraft(mPathForEdition);
SetDirtyState(false);
ShowContent(
FileReader.ReadFile(mPathForEdition, mEncoding),
SyntaxLanguageFactory.GetSyntaxLanguage(
BaseServices.CalcFileSize(
mPathForEdition, true),
Path.GetExtension(mPathForEdition),
UnitySyntaxLanguages.AdditionalExtensions),
true);
}
internal void DeleteDraft()
{
DraftStorage.DeleteDraft(mPathForEdition);
}
internal void FinishPendingDraftSave()
{
mScheduledDraftSave?.Pause();
mScheduledDraftSave = null;
SaveDraftIfDirty();
}
internal void Dispose()
{
FinishPendingDraftSave();
mTextEditor.TextChanged -=
TextEditor_TextChanged;
mTextMateInstallation.Dispose();
mTextEditorContextMenu.Dispose();
mTextEditorSaveKeyBinding.Dispose();
}
void TextEditor_TextChanged(
object sender, EventArgs e)
{
if (mbIsUpdatingTextBox)
return;
SetDirtyState(true);
ScheduleDraftSave();
}
void SetDirtyState(bool isDirty)
{
bool changed = IsTextDirty != isDirty;
IsTextDirty = isDirty;
if (changed)
DirtyStateChanged?.Invoke(isDirty);
}
void ScheduleDraftSave()
{
if (string.IsNullOrEmpty(mPathForEdition))
return;
mScheduledDraftSave?.Pause();
mScheduledDraftSave = this.schedule
.Execute(SaveDraft)
.StartingIn(DRAFT_SAVE_DELAY_MS);
}
void SaveDraftIfDirty()
{
if (!IsTextDirty)
return;
DraftStorage.SaveDraft(
mPathForEdition, mTextEditor.Text);
}
void SaveDraft()
{
mScheduledDraftSave = null;
SaveDraftIfDirty();
}
Unity.CodeEditor.TextEditor mTextEditor;
TextMate.Installation mTextMateInstallation;
DiffTextViewContextMenu mTextEditorContextMenu;
TextEditorSaveKeyBinding mTextEditorSaveKeyBinding;
string mPathForEdition;
Encoding mEncoding;
bool mbIsUpdatingTextBox;
Language mCurrentLanguage = Language.PlainText;
IVisualElementScheduledItem mScheduledDraftSave;
const long DRAFT_SAVE_DELAY_MS = 1000;
}
}