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

420 lines
15 KiB
C#

using System;
using System.IO;
using System.Text;
using Codice.Client.Common.Threading;
using Codice.CM.Client.Differences;
using Codice.CM.Client.Differences.Graphic;
using Codice.LogWrapper;
using MergetoolGui;
using XDiffGui;
using XDiffGui.Options;
namespace Unity.PlasticSCM.Editor.Diff.Text
{
internal interface IRunAfterSetDifferencesInfo
{
// This needs to run *always after* IDiffControl.SetDifferencesInfo
void Run();
}
internal static class DiffMessage
{
public static string Get(
string initialMessage, bool bHasDifferences)
{
if (bHasDifferences)
return initialMessage;
string filesIdenticalMessage = MergetoolLocalization.GetString(
MergetoolLocalization.Name.FilesIdentical);
if (string.IsNullOrEmpty(initialMessage))
return filesIdenticalMessage;
return string.Format("{0} {1}", filesIdenticalMessage, initialMessage);
}
}
internal static class DiffControlOperations
{
public interface IDiffControl
{
void ShowDiffPanel();
void ShowWaitingAnimation();
void HideWaitingAnimation();
void ClearNavigationPanel();
void SetOptionsContextMenuButtonInfo(
ComparisonMethodTypes comparisonMethod,
Language syntaxHighlightLanguage,
DiffViewerData diffInfo);
void UpdateTextContent(
DiffContent leftContent, DiffContent rightContent);
void SetSyntaxLanguage(Language language);
Language GetSyntaxLanguage();
void SetEditable(bool editable);
void OnRightTextBoxClean();
void SetDiffDrawingInfo(DiffDrawingInfo diffDrawingInfo);
void SetDifferencesInfo(
DiffDrawingInfo diffDrawingInfo,
DiffViewerData diffData);
void UpdateDifferencesInfoSilently(DiffDrawingInfo diffDrawingInfo);
void HandleException(Exception e);
void EnableBigFileMessagePanel();
void DisableBigFileMessagePanel();
}
internal static void AsyncCalculateDiff(
IDiffControl diffControl,
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
ComparisonMethodTypes comparisonMethod,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader,
DiffCalculatorSync syncCalculator)
{
diffControl.ShowDiffPanel();
diffControl.OnRightTextBoxClean();
diffControl.ClearNavigationPanel();
DiffCalculator calculator = BuildDiffCalculator(
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader);
syncCalculator.ReplaceCurrentDiffCalculation(calculator);
diffControl.ShowWaitingAnimation();
Language language = SyntaxLanguageFactory.GetSyntaxLanguage(
FileSizeCalculator.GetMaxFileSize(
diffViewerData.Left.File, diffViewerData.Right.File),
Path.GetExtension(diffViewerData.Left.File));
IThreadWaiter waiter = ThreadWaiter.GetWaiter(TIMER_INTERVAL);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mLog.Info(
"AsyncCalculateDiff thread about to CalculateDiff");
calculator.CalculateDiff();
},
/*afterOperationDelegate*/ delegate
{
diffControl.HideWaitingAnimation();
DiffCalculator.Result result = calculator.GetResult();
diffControl.SetDiffDrawingInfo(result.DiffDrawingInfo);
diffControl.SetOptionsContextMenuButtonInfo(
comparisonMethod, language, diffViewerData);
if (language != diffControl.GetSyntaxLanguage())
diffControl.SetSyntaxLanguage(Language.PlainText);
diffControl.UpdateTextContent(
result.LeftContent, result.RightContent);
bool isEditable = diffViewerData.IsEditable;
diffControl.SetEditable(isEditable);
diffControl.SetSyntaxLanguage(language);
if (waiter.Exception != null)
{
syncCalculator.CleanCurrentDiffCalculation();
diffControl.HandleException(waiter.Exception);
return;
}
diffControl.SetDifferencesInfo(
result.DiffDrawingInfo,
diffViewerData);
syncCalculator.CleanCurrentDiffCalculation();
/*if (runAfterSetDifferencesInfo != null)
runAfterSetDifferencesInfo.Run();*/
/*TrackDiffEvent.FileDiff(
diffViewerData, isSemanticDiff && useSemanticDiff, result);*/
});
}
internal static void ComparisonMethodChanged(
ComparisonMethodTypes comparisonMethod,
IDiffControl diffControl,
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader,
DiffCalculatorSync syncCalculator)
{
DiffCalculator calculator = BuildDiffCalculator(
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader);
if (!syncCalculator.TrySetCurrentDiffCalculation(calculator))
return;
diffControl.ShowWaitingAnimation();
IThreadWaiter waiter = ThreadWaiter.GetWaiter(TIMER_INTERVAL);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mLog.Info("OnComparisonMethodChanged thread about to " +
"recalculate diff with a different comparison method");
calculator.CalculateDiff();
},
/*afterOperationDelegate*/ delegate
{
if (!syncCalculator.IsCurrentDiffCalculation(calculator))
return;
diffControl.HideWaitingAnimation();
if (waiter.Exception != null)
{
syncCalculator.CleanCurrentDiffCalculation();
diffControl.HandleException(waiter.Exception);
return;
}
DiffCalculator.Result result = calculator.GetResult();
diffControl.SetDiffDrawingInfo(result.DiffDrawingInfo);
diffControl.SetDifferencesInfo(
result.DiffDrawingInfo,
diffViewerData);
syncCalculator.CleanCurrentDiffCalculation();
});
}
internal static void CalculateDifferencesButtonClick(
IBigFileDownloader bigFileDownloader,
IDiffControl diffControl,
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
ComparisonMethodTypes comparisonMethod,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader,
DiffCalculatorSync syncCalculator,
Encoding defaultEncoding,
Action<DiffViewerData> onPurgedDetected = null)
{
if (bigFileDownloader == null)
{
AsyncCalculateDiff(
diffControl,
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader,
syncCalculator);
return;
}
diffControl.DisableBigFileMessagePanel();
diffControl.ShowWaitingAnimation();
IThreadWaiter waiter = ThreadWaiter.GetWaiter(TIMER_INTERVAL);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mLog.Info(
"OnCalculateDifferencesButtonClick thread about to DownloadFiles");
bigFileDownloader.DownloadFiles(diffViewerData, defaultEncoding);
},
/*afterOperationDelegate*/ delegate
{
diffControl.HideWaitingAnimation();
diffControl.EnableBigFileMessagePanel();
if (waiter.Exception != null)
{
syncCalculator.CleanCurrentDiffCalculation();
diffControl.HandleException(waiter.Exception);
return;
}
if (onPurgedDetected != null &&
(diffViewerData.Left?.IsPurged == true ||
diffViewerData.Right?.IsPurged == true))
{
onPurgedDetected(diffViewerData);
return;
}
AsyncCalculateDiff(
diffControl,
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader,
syncCalculator);
});
}
internal static bool EncodingChanged(
TextBoxContributor contributor,
Encoding encoding,
IDiffControl diffControl,
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
ComparisonMethodTypes comparisonMethod,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader,
DiffCalculatorSync syncCalculator)
{
diffControl.OnRightTextBoxClean();
DiffCalculator calculator = BuildDiffCalculator(
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader);
if (!syncCalculator.TrySetCurrentDiffCalculation(calculator))
return false;
bool bLeftFile = contributor == TextBoxContributor.Left;
if (bLeftFile)
diffViewerData.Left.Encoding = encoding;
else
diffViewerData.Right.Encoding = encoding;
diffControl.ShowWaitingAnimation();
IThreadWaiter waiter = ThreadWaiter.GetWaiter(TIMER_INTERVAL);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
mLog.Info("OnEncodingChanged thread about to recalculate " +
"diff with a different encoding");
calculator.CalculateDiff();
},
/*afterOperationDelegate*/ delegate
{
if (!syncCalculator.IsCurrentDiffCalculation(calculator))
return;
diffControl.HideWaitingAnimation();
if (waiter.Exception != null)
{
syncCalculator.CleanCurrentDiffCalculation();
diffControl.HandleException(waiter.Exception);
return;
}
DiffCalculator.Result result = calculator.GetResult();
diffControl.SetDiffDrawingInfo(result.DiffDrawingInfo);
diffControl.UpdateTextContent(
result.LeftContent, result.RightContent);
diffControl.SetDifferencesInfo(
result.DiffDrawingInfo,
diffViewerData);
syncCalculator.CleanCurrentDiffCalculation();
});
return true;
}
internal static void OnRightTextViewContentChanged(
IDiffControl diffControl,
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
ComparisonMethodTypes comparisonMethod,
bool isRightTextBoxDirty,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader,
DiffCalculatorSync syncCalculator)
{
DiffCalculator calculator = BuildDiffCalculator(
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader);
syncCalculator.ReplaceCurrentDiffCalculation(calculator);
IThreadWaiter waiter = ThreadWaiter.GetWaiter(TIMER_INTERVAL);
waiter.Execute(
/*threadOperationDelegate*/ delegate
{
calculator.CalculateDiff();
},
/*afterOperationDelegate*/ delegate
{
if (!syncCalculator.IsCurrentDiffCalculation(calculator))
return;
if (waiter.Exception != null)
{
syncCalculator.CleanCurrentDiffCalculation();
diffControl.HandleException(waiter.Exception);
return;
}
DiffCalculator.Result result = calculator.GetResult();
diffControl.SetDiffDrawingInfo(result.DiffDrawingInfo);
diffControl.UpdateDifferencesInfoSilently(
result.DiffDrawingInfo);
syncCalculator.CleanCurrentDiffCalculation();
});
}
static DiffCalculator BuildDiffCalculator(
DiffViewerData diffViewerData,
MovedDetectionOptionsInfo movedDetectionOptions,
ComparisonMethodTypes comparisonMethod,
IDiffContent rightContentForEdition,
IDiffContentLoader contentLoader)
{
return new DiffCalculator(
diffViewerData,
movedDetectionOptions,
comparisonMethod,
rightContentForEdition,
contentLoader);
}
const int TIMER_INTERVAL = 10;
static readonly ILog mLog = LogManager.GetLogger("DiffControl");
}
}