diff --git a/Flow.Launcher.Plugin/GlyphInfo.cs b/Flow.Launcher.Plugin/GlyphInfo.cs new file mode 100644 index 00000000000..d24624d8f50 --- /dev/null +++ b/Flow.Launcher.Plugin/GlyphInfo.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; + +namespace Flow.Launcher.Plugin +{ + public record GlyphInfo(string FontFamily, string Glyph); +} diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index ac9c10df05b..171b30c2675 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -47,7 +47,15 @@ public string IcoPath public delegate ImageSource IconDelegate(); - public IconDelegate Icon; + /// + /// Delegate to Get Image Source + /// + public IconDelegate Icon { get; set; } + + /// + /// Information for Glyph Icon + /// + public GlyphInfo Glyph { get; init; } /// diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml index 0f70dce4103..dfee8981072 100644 --- a/Flow.Launcher/ResultListBox.xaml +++ b/Flow.Launcher/ResultListBox.xaml @@ -42,7 +42,10 @@ + Source="{Binding Image}" Visibility="{Binding ShowIcon}" /> + diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 190f592d774..328dbcba5f6 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -6,6 +6,7 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using System.IO; namespace Flow.Launcher.ViewModel { @@ -16,24 +17,49 @@ public ResultViewModel(Result result, Settings settings) if (result != null) { Result = result; + + if (Result.Glyph is { FontFamily: not null } glyph) + { + // Checks if it's a system installed font, which does not require path to be provided. + if (glyph.FontFamily.EndsWith(".ttf") || glyph.FontFamily.EndsWith(".otf")) + { + var fontPath = Result.Glyph.FontFamily; + Glyph = Path.IsPathRooted(fontPath) + ? Result.Glyph + : Result.Glyph with + { + FontFamily = Path.Combine(Result.PluginDirectory, fontPath) + }; + } + else + { + Glyph = glyph; + } + } } Settings = settings; } - public Settings Settings { get; private set; } + private Settings Settings { get; } + + public Visibility ShowOpenResultHotkey => + Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Hidden; - public Visibility ShowOpenResultHotkey => Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Hidden; + public Visibility ShowIcon => Result.IcoPath != null || Result.Icon is not null || Glyph == null + ? Visibility.Visible + : Visibility.Hidden; + public Visibility ShowGlyph => Glyph is not null ? Visibility.Visible : Visibility.Hidden; public string OpenResultModifiers => Settings.OpenResultModifiers; public string ShowTitleToolTip => string.IsNullOrEmpty(Result.TitleToolTip) - ? Result.Title - : Result.TitleToolTip; + ? Result.Title + : Result.TitleToolTip; public string ShowSubTitleToolTip => string.IsNullOrEmpty(Result.SubTitleToolTip) - ? Result.SubTitle - : Result.SubTitleToolTip; + ? Result.SubTitle + : Result.SubTitleToolTip; private volatile bool ImageLoaded; @@ -48,10 +74,14 @@ public ImageSource Image ImageLoaded = true; _ = LoadImageAsync(); } + return image; } private set => image = value; } + + public GlyphInfo Glyph { get; set; } + private async ValueTask LoadImageAsync() { var imagePath = Result.IcoPath; @@ -64,7 +94,9 @@ private async ValueTask LoadImageAsync() } catch (Exception e) { - Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); + Log.Exception( + $"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", + e); } } @@ -74,7 +106,7 @@ private async ValueTask LoadImageAsync() image = ImageLoader.Load(imagePath); return; } - + // We need to modify the property not field here to trigger the OnPropertyChanged event Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false); }