You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
using System; |
|
using System.Diagnostics; |
|
using System.IO; |
|
using AsyncAwaitBestPractices; |
|
using Avalonia; |
|
using Avalonia.Controls; |
|
using Avalonia.Controls.Presenters; |
|
using Avalonia.Logging; |
|
using FluentAvalonia.UI.Controls; |
|
using StabilityMatrix.Core.Processes; |
|
using Symbol = FluentIcons.Common.Symbol; |
|
|
|
namespace StabilityMatrix.Avalonia.Controls; |
|
|
|
/// <summary> |
|
/// Like <see cref="HyperlinkButton"/>, but with a link icon left of the text content. |
|
/// </summary> |
|
public class HyperlinkIconButton : Button |
|
{ |
|
private Uri? _navigateUri; |
|
|
|
/// <summary> |
|
/// Defines the <see cref="NavigateUri"/> property |
|
/// </summary> |
|
public static readonly DirectProperty<HyperlinkIconButton, Uri?> NavigateUriProperty = |
|
AvaloniaProperty.RegisterDirect<HyperlinkIconButton, Uri?>( |
|
nameof(NavigateUri), |
|
x => x.NavigateUri, |
|
(x, v) => x.NavigateUri = v |
|
); |
|
|
|
/// <summary> |
|
/// Gets or sets the Uri that the button should navigate to upon clicking. In assembly paths are not supported, (e.g., avares://...) |
|
/// </summary> |
|
public Uri? NavigateUri |
|
{ |
|
get => _navigateUri; |
|
set => SetAndRaise(NavigateUriProperty, ref _navigateUri, value); |
|
} |
|
|
|
public static readonly StyledProperty<Symbol> IconProperty = AvaloniaProperty.Register< |
|
HyperlinkIconButton, |
|
Symbol |
|
>("Icon", Symbol.Link); |
|
|
|
public Symbol Icon |
|
{ |
|
get => GetValue(IconProperty); |
|
set => SetValue(IconProperty, value); |
|
} |
|
|
|
protected override Type StyleKeyOverride => typeof(HyperlinkIconButton); |
|
|
|
/// <inheritdoc /> |
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) |
|
{ |
|
base.OnPropertyChanged(change); |
|
|
|
// Update icon |
|
if (change.Property == NavigateUriProperty) |
|
{ |
|
var uri = change.GetNewValue<Uri?>(); |
|
|
|
if (uri is not null && uri.IsFile && Icon == Symbol.Link) |
|
{ |
|
Icon = Symbol.Open; |
|
} |
|
} |
|
} |
|
|
|
protected override void OnClick() |
|
{ |
|
base.OnClick(); |
|
|
|
if (NavigateUri is null) |
|
return; |
|
|
|
// File or Folder URIs |
|
if (NavigateUri.IsFile) |
|
{ |
|
var path = NavigateUri.LocalPath; |
|
|
|
if (Directory.Exists(path)) |
|
{ |
|
ProcessRunner |
|
.OpenFolderBrowser(path) |
|
.SafeFireAndForget(ex => |
|
{ |
|
Logger.TryGet(LogEventLevel.Error, $"Unable to open directory Uri {NavigateUri}"); |
|
}); |
|
} |
|
else if (File.Exists(path)) |
|
{ |
|
ProcessRunner |
|
.OpenFileBrowser(path) |
|
.SafeFireAndForget(ex => |
|
{ |
|
Logger.TryGet(LogEventLevel.Error, $"Unable to open file Uri {NavigateUri}"); |
|
}); |
|
} |
|
} |
|
// Web |
|
else |
|
{ |
|
try |
|
{ |
|
Process.Start( |
|
new ProcessStartInfo(NavigateUri.ToString()) { UseShellExecute = true, Verb = "open" } |
|
); |
|
} |
|
catch |
|
{ |
|
Logger.TryGet(LogEventLevel.Error, $"Unable to open Uri {NavigateUri}"); |
|
} |
|
} |
|
} |
|
|
|
protected override bool RegisterContentPresenter(ContentPresenter presenter) |
|
{ |
|
return presenter.Name == "ContentPresenter"; |
|
} |
|
}
|
|
|