This commit is contained in:
4sval
2023-05-07 03:31:16 +02:00
parent 2c099efd2b
commit 2bf6c245d9
11 changed files with 181 additions and 152 deletions

View File

@@ -177,9 +177,11 @@ public partial class MainWindow
if (AssetsFolderName.SelectedItem is TreeItem folder)
{
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.ExportFolder(cancellationToken, folder); });
FLogger.AppendInformation();
FLogger.AppendText("Successfully exported ", Constants.WHITE);
FLogger.AppendLink(folder.PathAtThisPoint, UserSettings.Default.RawDataDirectory, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully exported ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.RawDataDirectory, true);
});
}
}
@@ -188,9 +190,11 @@ public partial class MainWindow
if (AssetsFolderName.SelectedItem is TreeItem folder)
{
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.SaveFolder(cancellationToken, folder); });
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(folder.PathAtThisPoint, UserSettings.Default.PropertiesDirectory, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.PropertiesDirectory, true);
});
}
}
@@ -199,9 +203,11 @@ public partial class MainWindow
if (AssetsFolderName.SelectedItem is TreeItem folder)
{
await _threadWorkerView.Begin(cancellationToken => { _applicationView.CUE4Parse.TextureFolder(cancellationToken, folder); });
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(folder.PathAtThisPoint, UserSettings.Default.TextureDirectory, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(folder.PathAtThisPoint, UserSettings.Default.TextureDirectory, true);
});
}
}
@@ -226,8 +232,8 @@ public partial class MainWindow
if (AssetsFolderName.SelectedItem is not TreeItem folder) return;
_applicationView.CustomDirectories.Add(new CustomDirectory(folder.Header, folder.PathAtThisPoint));
FLogger.AppendInformation();
FLogger.AppendText($"Successfully saved '{folder.PathAtThisPoint}' as a new custom directory", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Successfully saved '{folder.PathAtThisPoint}' as a new custom directory", Constants.WHITE, true));
}
private void OnCopyDirectoryPathClick(object sender, RoutedEventArgs e)

View File

@@ -175,8 +175,7 @@ public class ApplicationViewModel : ViewModel
}
else
{
FLogger.AppendError();
FLogger.AppendText("Could not download VgmStream", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text("Could not download VgmStream", Constants.WHITE, true));
}
}
@@ -216,8 +215,7 @@ public class ApplicationViewModel : ViewModel
await ApplicationService.ApiEndpointView.DownloadFileAsync("https://cdn.fmodel.app/d/configurations/imgui.ini", imgui);
if (new FileInfo(imgui).Length == 0)
{
FLogger.AppendError();
FLogger.AppendText("Could not download ImGui settings", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text("Could not download ImGui settings", Constants.WHITE, true));
}
}
}

View File

@@ -328,15 +328,16 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable
if (File.Exists(path))
{
Log.Information("{FileName} successfully saved", fileToSave.FileName);
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(fileToSave.FileName, path, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(fileToSave.FileName, path, true);
});
}
else
{
Log.Error("{FileName} could not be saved", fileToSave.FileName);
FLogger.AppendError();
FLogger.AppendText($"Could not save '{fileToSave.FileName}'", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not save '{fileToSave.FileName}'", Constants.WHITE, true));
}
}

View File

@@ -103,15 +103,16 @@ public class BackupManagerViewModel : ViewModel
if (new FileInfo(fullPath).Length > 0)
{
Log.Information("{FileName} successfully {Type}", fileName, type1);
FLogger.AppendInformation();
FLogger.AppendText($"Successfully {type1} ", Constants.WHITE);
FLogger.AppendLink(fileName, fullPath, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text($"Successfully {type1} ", Constants.WHITE);
FLogger.Link(fileName, fullPath, true);
});
}
else
{
Log.Error("{FileName} could not be {Type}", fileName, type1);
FLogger.AppendError();
FLogger.AppendText($"Could not {type2} '{fileName}'", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not {type2} '{fileName}'", Constants.WHITE, true));
}
}
}

View File

@@ -251,10 +251,10 @@ public class CUE4ParseViewModel : ViewModel
, it => new FStreamArchive(it, manifest.FileManifests.First(x => x.Name.Equals(it)).GetStream(), p.Versions));
}
FLogger.AppendInformation();
FLogger.AppendText($"Fortnite has been loaded successfully in {manifest.ParseTime.TotalMilliseconds}ms", Constants.WHITE, true);
FLogger.AppendWarning();
FLogger.AppendText($"Mappings must match '{manifest.BuildVersion}' in order to avoid errors", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Fortnite has been loaded successfully in {manifest.ParseTime.TotalMilliseconds}ms", Constants.WHITE, true));
FLogger.Append(ELog.Warning, () =>
FLogger.Text($"Mappings must match '{manifest.BuildVersion}' in order to avoid errors", Constants.WHITE, true));
break;
}
case "ValorantLive":
@@ -270,8 +270,8 @@ public class CUE4ParseViewModel : ViewModel
p.Initialize(manifestInfo.Paks[i].GetFullName(), new[] { manifestInfo.GetPakStream(i) });
}
FLogger.AppendInformation();
FLogger.AppendText($"Valorant '{manifestInfo.Header.GameVersion}' has been loaded successfully", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Valorant '{manifestInfo.Header.GameVersion}' has been loaded successfully", Constants.WHITE, true));
break;
}
}
@@ -364,10 +364,13 @@ public class CUE4ParseViewModel : ViewModel
var info = _apiEndpointView.FModelApi.GetNews(cancellationToken, Provider.GameName);
if (info == null) return;
for (var i = 0; i < info.Messages.Length; i++)
FLogger.Append(ELog.None, () =>
{
FLogger.AppendText(info.Messages[i], info.Colors[i], bool.Parse(info.NewLines[i]));
}
for (var i = 0; i < info.Messages.Length; i++)
{
FLogger.Text(info.Messages[i], info.Colors[i], bool.Parse(info.NewLines[i]));
}
});
});
}
@@ -384,8 +387,8 @@ public class CUE4ParseViewModel : ViewModel
if (endpoint.Overwrite && File.Exists(endpoint.FilePath))
{
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(endpoint.FilePath);
FLogger.AppendInformation();
FLogger.AppendText($"Mappings pulled from '{endpoint.FilePath.SubstringAfterLast("\\")}'", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Mappings pulled from '{endpoint.FilePath.SubstringAfterLast("\\")}'", Constants.WHITE, true));
}
else if (endpoint.IsValid)
{
@@ -404,8 +407,8 @@ public class CUE4ParseViewModel : ViewModel
}
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(mappingPath);
FLogger.AppendInformation();
FLogger.AppendText($"Mappings pulled from '{mapping.FileName}'", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Mappings pulled from '{mapping.FileName}'", Constants.WHITE, true));
break;
}
}
@@ -417,8 +420,8 @@ public class CUE4ParseViewModel : ViewModel
var latestUsmapInfo = latestUsmaps.OrderBy(f => f.LastWriteTime).Last();
Provider.MappingsContainer = new FileUsmapTypeMappingsProvider(latestUsmapInfo.FullName);
FLogger.AppendWarning();
FLogger.AppendText($"Mappings pulled from '{latestUsmapInfo.Name}'", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text($"Mappings pulled from '{latestUsmapInfo.Name}'", Constants.WHITE, true));
}
}
});
@@ -434,8 +437,8 @@ public class CUE4ParseViewModel : ViewModel
Provider.DefaultEngine.FindPropertyInstructions("ConsoleVariables", "a.StripAdditiveRefPose", inst);
if (inst.Count > 0 && inst[0].Value.Equals("1"))
{
FLogger.AppendWarning();
FLogger.AppendText("Additive animations have their reference pose stripped, which will lead to inaccurate preview and export", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text("Additive animations have their reference pose stripped, which will lead to inaccurate preview and export", Constants.WHITE, true));
}
}
@@ -446,10 +449,8 @@ public class CUE4ParseViewModel : ViewModel
_vfcCount = Provider.LoadVirtualCache();
if (_vfcCount > 0)
{
FLogger.AppendInformation();
FLogger.AppendText($"VFC loaded {_vfcCount} cached packages", Constants.WHITE, true);
}
FLogger.Append(ELog.Information, () =>
FLogger.Text($"VFC loaded {_vfcCount} cached packages", Constants.WHITE, true));
}
public int LocalizedResourcesCount { get; set; }
@@ -458,13 +459,13 @@ public class CUE4ParseViewModel : ViewModel
await Task.WhenAll(LoadGameLocalizedResources(), LoadHotfixedLocalizedResources()).ConfigureAwait(false);
if (LocalizedResourcesCount > 0)
{
FLogger.AppendInformation();
FLogger.AppendText($"{LocalizedResourcesCount} localized resources loaded for '{UserSettings.Default.AssetLanguage.GetDescription()}'", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"{LocalizedResourcesCount} localized resources loaded for '{UserSettings.Default.AssetLanguage.GetDescription()}'", Constants.WHITE, true));
}
else
{
FLogger.AppendWarning();
FLogger.AppendText($"Could not load localized resources in '{UserSettings.Default.AssetLanguage.GetDescription()}', language may not exist", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text($"Could not load localized resources in '{UserSettings.Default.AssetLanguage.GetDescription()}', language may not exist", Constants.WHITE, true));
}
}
@@ -512,13 +513,13 @@ public class CUE4ParseViewModel : ViewModel
_virtualPathCount = Provider.LoadVirtualPaths(UserSettings.Default.OverridedGame[Game].GetVersion());
if (_virtualPathCount > 0)
{
FLogger.AppendInformation();
FLogger.AppendText($"{_virtualPathCount} virtual paths loaded", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"{_virtualPathCount} virtual paths loaded", Constants.WHITE, true));
}
else
{
FLogger.AppendWarning();
FLogger.AppendText("Could not load virtual paths, plugin manifest may not exist", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text("Could not load virtual paths, plugin manifest may not exist", Constants.WHITE, true));
}
});
}
@@ -754,8 +755,8 @@ public class CUE4ParseViewModel : ViewModel
case "ufont":
case "otf":
case "ttf":
FLogger.AppendWarning();
FLogger.AppendText($"Export '{fileName}' raw data and change its extension if you want it to be an installable font file", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text($"Export '{fileName}' raw data and change its extension if you want it to be an installable font file", Constants.WHITE, true));
break;
case "ushaderbytecode":
case "ushadercode":
@@ -770,8 +771,8 @@ public class CUE4ParseViewModel : ViewModel
}
default:
{
FLogger.AppendWarning();
FLogger.AppendText($"The package '{fileName}' is of an unknown type.", Constants.WHITE, true);
FLogger.Append(ELog.Warning, () =>
FLogger.Text($"The package '{fileName}' is of an unknown type.", Constants.WHITE, true));
break;
}
}
@@ -934,15 +935,16 @@ public class CUE4ParseViewModel : ViewModel
if (toSave.TryWriteToDir(toSaveDirectory, out var label, out var savedFilePath))
{
Log.Information("Successfully saved {FilePath}", savedFilePath);
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(label, savedFilePath, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(label, savedFilePath, true);
});
}
else
{
Log.Warning("{FileName} could not be saved", export.Name);
FLogger.AppendWarning();
FLogger.AppendText($"Could not save '{export.Name}'", Constants.WHITE, true);
Log.Error("{FileName} could not be saved", export.Name);
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not save '{export.Name}'", Constants.WHITE, true));
}
}
@@ -966,19 +968,18 @@ public class CUE4ParseViewModel : ViewModel
Log.Information("{FileName} successfully exported", fileName);
if (updateUi)
{
FLogger.AppendInformation();
FLogger.AppendText("Successfully exported ", Constants.WHITE);
FLogger.AppendLink(fileName, path, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully exported ", Constants.WHITE);
FLogger.Link(fileName, path, true);
});
}
}
else
{
Log.Error("{FileName} could not be exported", fileName);
if (updateUi)
{
FLogger.AppendError();
FLogger.AppendText($"Could not export '{fileName}'", Constants.WHITE, true);
}
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not export '{fileName}'", Constants.WHITE, true));
}
}

View File

@@ -40,8 +40,8 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
if (_applicationView.CUE4Parse.GameDirectory.HasNoFile) return;
if (_applicationView.CUE4Parse.Provider.Files.Count <= 0)
{
FLogger.AppendError();
FLogger.AppendText("An encrypted archive has been found. In order to decrypt it, please specify a working AES encryption key", Constants.WHITE, true);
FLogger.Append(ELog.Error, () =>
FLogger.Text("An encrypted archive has been found. In order to decrypt it, please specify a working AES encryption key", Constants.WHITE, true));
return;
}
@@ -91,8 +91,8 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
).ConfigureAwait(false);
#if DEBUG
loadingTime.Stop();
FLogger.AppendDebug();
FLogger.AppendText($"{_applicationView.CUE4Parse.SearchVm.SearchResults.Count} packages loaded in {loadingTime.Elapsed.TotalSeconds.ToString("F3", CultureInfo.InvariantCulture)} seconds", Constants.WHITE, true);
FLogger.Append(ELog.Debug, () =>
FLogger.Text($"{_applicationView.CUE4Parse.SearchVm.SearchResults.Count} packages loaded in {loadingTime.Elapsed.TotalSeconds.ToString("F3", CultureInfo.InvariantCulture)} seconds", Constants.WHITE, true));
#endif
}
@@ -153,8 +153,8 @@ public class LoadCommand : ViewModelCommand<LoadingModesViewModel>
if (!openFileDialog.ShowDialog().GetValueOrDefault()) return;
FLogger.AppendInformation();
FLogger.AppendText($"Backup file older than current game is '{openFileDialog.FileName.SubstringAfterLast("\\")}'", Constants.WHITE, true);
FLogger.Append(ELog.Information, () =>
FLogger.Text($"Backup file older than current game is '{openFileDialog.FileName.SubstringAfterLast("\\")}'", Constants.WHITE, true));
using var fileStream = new FileStream(openFileDialog.FileName, FileMode.Open);
using var memoryStream = new MemoryStream();

View File

@@ -318,19 +318,18 @@ public class TabItem : ViewModel
Log.Information("{FileName} successfully saved", fileName);
if (updateUi)
{
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(fileName, path, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(fileName, path, true);
});
}
}
else
{
Log.Error("{FileName} could not be saved", fileName);
if (updateUi)
{
FLogger.AppendError();
FLogger.AppendText($"Could not save '{fileName}'", Constants.WHITE, true);
}
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not save '{fileName}'", Constants.WHITE, true));
}
}
}

View File

@@ -105,34 +105,36 @@ public class ThreadWorkerViewModel : ViewModel
Log.Error("{Exception}", e);
FLogger.AppendError();
if ((e.InnerException ?? e) is { TargetSite.DeclaringType: not null } exception)
FLogger.Append(ELog.Error, () =>
{
if (exception.TargetSite.ToString() == "CUE4Parse.FileProvider.GameFile get_Item(System.String)")
if ((e.InnerException ?? e) is { TargetSite.DeclaringType: not null } exception)
{
FLogger.AppendText(e.Message, Constants.WHITE, true);
}
else
{
var t = exception.GetType();
FLogger.AppendText(t.Namespace + _dot, Constants.GRAY);
FLogger.AppendText(t.Name, Constants.WHITE);
FLogger.AppendText(_colon + " ", Constants.GRAY);
FLogger.AppendText(exception.Message, Constants.RED, true);
FLogger.AppendText(_at, _gray);
FLogger.AppendText(exception.TargetSite.DeclaringType.FullName + _dot, Constants.GRAY);
FLogger.AppendText(exception.TargetSite.Name, Constants.YELLOW);
var p = exception.TargetSite.GetParameters();
var parameters = new string[p.Length];
for (int i = 0; i < parameters.Length; i++)
if (exception.TargetSite.ToString() == "CUE4Parse.FileProvider.GameFile get_Item(System.String)")
{
parameters[i] = p[i].ParameterType.Name + " " + p[i].Name;
FLogger.Text(e.Message, Constants.WHITE, true);
}
else
{
var t = exception.GetType();
FLogger.Text(t.Namespace + _dot, Constants.GRAY);
FLogger.Text(t.Name, Constants.WHITE);
FLogger.Text(_colon + " ", Constants.GRAY);
FLogger.Text(exception.Message, Constants.RED, true);
FLogger.Text(_at, _gray);
FLogger.Text(exception.TargetSite.DeclaringType.FullName + _dot, Constants.GRAY);
FLogger.Text(exception.TargetSite.Name, Constants.YELLOW);
var p = exception.TargetSite.GetParameters();
var parameters = new string[p.Length];
for (int i = 0; i < parameters.Length; i++)
{
parameters[i] = p[i].ParameterType.Name + " " + p[i].Name;
}
FLogger.Text("(" + string.Join(", ", parameters) + ")", Constants.GRAY, true);
}
FLogger.AppendText("(" + string.Join(", ", parameters) + ")", Constants.GRAY, true);
}
}
});
return;
}
}

View File

@@ -281,15 +281,16 @@ public partial class ImageMerger
if (File.Exists(path))
{
Log.Information("{FileName} successfully saved", fileName);
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved ", Constants.WHITE);
FLogger.AppendLink(fileName, path, true);
FLogger.Append(ELog.Information, () =>
{
FLogger.Text("Successfully saved ", Constants.WHITE);
FLogger.Link(fileName, path, true);
});
}
else
{
Log.Error("{FileName} could not be saved", fileName);
FLogger.AppendError();
FLogger.AppendText($"Could not save '{fileName}'", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text($"Could not save '{fileName}'", Constants.WHITE, true));
}
}

View File

@@ -51,14 +51,12 @@ public partial class MapViewer
if (File.Exists(path))
{
Log.Information("MiniMap.png successfully saved");
FLogger.AppendInformation();
FLogger.AppendText("Successfully saved 'MiniMap.png'", Constants.WHITE, true);
FLogger.Append(ELog.Information, () => FLogger.Text("Successfully saved 'MiniMap.png'", Constants.WHITE, true));
}
else
{
Log.Error("MiniMap.png could not be saved");
FLogger.AppendError();
FLogger.AppendText("Could not save 'MiniMap.png'", Constants.WHITE, true);
FLogger.Append(ELog.Error, () => FLogger.Text("Could not save 'MiniMap.png'", Constants.WHITE, true));
}
}
@@ -77,4 +75,4 @@ public partial class MapViewer
break;
}
}
}
}

View File

@@ -18,59 +18,81 @@ public interface ITextFormatter
void SetText(FlowDocument document, string text);
}
public enum ELog
{
Information,
Warning,
Error,
Debug,
None
}
public class FLogger : ITextFormatter
{
public static CustomRichTextBox Logger;
private static readonly BrushConverter _brushConverter = new();
private static int _previous;
public static void AppendInformation() => AppendText("[INF] ", Constants.BLUE);
public static void AppendWarning() => AppendText("[WRN] ", Constants.YELLOW);
public static void AppendError() => AppendText("[ERR] ", Constants.RED);
public static void AppendDebug() => AppendText("[DBG] ", Constants.GREEN);
public static void AppendText(string message, string color, bool newLine = false)
public static void Append(ELog type, Action job)
{
Application.Current.Dispatcher.Invoke(delegate
{
try
switch (type)
{
Logger.Document.ContentEnd.InsertTextInRun(message);
if (newLine) Logger.Document.ContentEnd.InsertLineBreak();
case ELog.Information:
Text("[INF] ", Constants.BLUE);
break;
case ELog.Warning:
Text("[WRN] ", Constants.YELLOW);
break;
case ELog.Error:
Text("[ERR] ", Constants.RED);
break;
case ELog.Debug:
Text("[DBG] ", Constants.GREEN);
break;
}
Logger.Selection.Select(Logger.Document.ContentStart.GetPositionAtOffset(_previous), Logger.Document.ContentEnd);
Logger.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, _brushConverter.ConvertFromString(color));
}
finally
{
Finally();
}
job();
});
}
public static void AppendLink(string message, string url, bool newLine = false)
public static void Text(string message, string color, bool newLine = false)
{
Application.Current.Dispatcher.Invoke(delegate
try
{
try
Logger.Document.ContentEnd.InsertTextInRun(message);
if (newLine) Logger.Document.ContentEnd.InsertLineBreak();
Logger.Selection.Select(Logger.Document.ContentStart.GetPositionAtOffset(_previous), Logger.Document.ContentEnd);
Logger.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, _brushConverter.ConvertFromString(color));
}
finally
{
Finally();
}
}
public static void Link(string message, string url, bool newLine = false)
{
try
{
new Hyperlink(new Run(newLine ? $"{message}{Environment.NewLine}" : message), Logger.Document.ContentEnd)
{
new Hyperlink(new Run(newLine ? $"{message}{Environment.NewLine}" : message), Logger.Document.ContentEnd)
NavigateUri = new Uri(url),
OverridesDefaultStyle = true,
Style = new Style(typeof(Hyperlink)) { Setters =
{
NavigateUri = new Uri(url),
OverridesDefaultStyle = true,
Style = new Style(typeof(Hyperlink)) { Setters =
{
new Setter(FrameworkContentElement.CursorProperty, Cursors.Hand),
new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline),
new Setter(TextElement.ForegroundProperty, Brushes.Cornsilk)
}}
}.Click += (sender, _) => Process.Start("explorer.exe", $"/select, \"{((Hyperlink)sender).NavigateUri.AbsoluteUri}\"");
}
finally
{
Finally();
}
});
new Setter(FrameworkContentElement.CursorProperty, Cursors.Hand),
new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline),
new Setter(TextElement.ForegroundProperty, Brushes.Cornsilk)
}}
}.Click += (sender, _) => Process.Start("explorer.exe", $"/select, \"{((Hyperlink)sender).NavigateUri.AbsoluteUri}\"");
}
finally
{
Finally();
}
}
private static void Finally()