Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix font select function #3377

Merged
merged 6 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 181 additions & 41 deletions Flow.Launcher.Core/Resource/Theme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Effects;
Expand All @@ -16,7 +17,6 @@
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Microsoft.Win32;
using TextBox = System.Windows.Controls.TextBox;

namespace Flow.Launcher.Core.Resource
{
Expand Down Expand Up @@ -56,20 +56,23 @@ public Theme(IPublicAPI publicAPI, Settings settings)
MakeSureThemeDirectoriesExist();

var dicts = Application.Current.Resources.MergedDictionaries;
_oldResource = dicts.First(d =>
_oldResource = dicts.FirstOrDefault(d =>
{
if (d.Source == null)
return false;
if (d.Source == null) return false;

var p = d.Source.AbsolutePath;
var dir = Path.GetDirectoryName(p).NonNull();
var info = new DirectoryInfo(dir);
var f = info.Name;
var e = Path.GetExtension(p);
var found = f == Folder && e == Extension;
return found;
return p.Contains(Folder) && Path.GetExtension(p) == Extension;
});
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);

if (_oldResource != null)
{
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
}
else
{
Log.Error("Current theme resource not found. Initializing with default theme.");
_oldTheme = Constant.DefaultTheme;
};
}

#endregion
Expand Down Expand Up @@ -98,13 +101,152 @@ private void MakeSureThemeDirectoriesExist()

private void UpdateResourceDictionary(ResourceDictionary dictionaryToUpdate)
{
var dicts = Application.Current.Resources.MergedDictionaries;
// Add new resources
if (!Application.Current.Resources.MergedDictionaries.Contains(dictionaryToUpdate))
{
Application.Current.Resources.MergedDictionaries.Add(dictionaryToUpdate);
}

// Remove old resources
if (_oldResource != null && _oldResource != dictionaryToUpdate &&
Application.Current.Resources.MergedDictionaries.Contains(_oldResource))
{
Application.Current.Resources.MergedDictionaries.Remove(_oldResource);
}

dicts.Remove(_oldResource);
dicts.Add(dictionaryToUpdate);
_oldResource = dictionaryToUpdate;
}

/// <summary>
/// Updates only the font settings and refreshes the UI.
/// </summary>
public void UpdateFonts()
{
try
{
// Load a ResourceDictionary for the specified theme.
var themeName = GetCurrentTheme();
var dict = GetThemeResourceDictionary(themeName);

// Apply font settings to the theme resource.
ApplyFontSettings(dict);
UpdateResourceDictionary(dict);

// Must apply blur and drop shadow effects
_ = RefreshFrameAsync();
}
catch (Exception e)
{
Log.Exception("Error occurred while updating theme fonts", e);
}
}

/// <summary>
/// Loads and applies font settings to the theme resource.
/// </summary>
private void ApplyFontSettings(ResourceDictionary dict)
{
if (dict["QueryBoxStyle"] is Style queryBoxStyle &&
dict["QuerySuggestionBoxStyle"] is Style querySuggestionBoxStyle)
{
var fontFamily = new FontFamily(_settings.QueryBoxFont);
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.QueryBoxFontStyle);
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.QueryBoxFontWeight);
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.QueryBoxFontStretch);

SetFontProperties(queryBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, true);
SetFontProperties(querySuggestionBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
}

if (dict["ItemTitleStyle"] is Style resultItemStyle &&
dict["ItemTitleSelectedStyle"] is Style resultItemSelectedStyle &&
dict["ItemHotkeyStyle"] is Style resultHotkeyItemStyle &&
dict["ItemHotkeySelectedStyle"] is Style resultHotkeyItemSelectedStyle)
{
var fontFamily = new FontFamily(_settings.ResultFont);
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultFontStyle);
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultFontWeight);
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultFontStretch);

SetFontProperties(resultItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
SetFontProperties(resultItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
SetFontProperties(resultHotkeyItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
SetFontProperties(resultHotkeyItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
}

if (dict["ItemSubTitleStyle"] is Style resultSubItemStyle &&
dict["ItemSubTitleSelectedStyle"] is Style resultSubItemSelectedStyle)
{
var fontFamily = new FontFamily(_settings.ResultSubFont);
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultSubFontStyle);
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultSubFontWeight);
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultSubFontStretch);

SetFontProperties(resultSubItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
SetFontProperties(resultSubItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
}
}

/// <summary>
/// Applies font properties to a Style.
/// </summary>
private static void SetFontProperties(Style style, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, bool isTextBox)
{
// Remove existing font-related setters
if (isTextBox)
{
// First, find the setters to remove and store them in a list
var settersToRemove = style.Setters
.OfType<Setter>()
.Where(setter =>
setter.Property == Control.FontFamilyProperty ||
setter.Property == Control.FontStyleProperty ||
setter.Property == Control.FontWeightProperty ||
setter.Property == Control.FontStretchProperty)
.ToList();

// Remove each found setter one by one
foreach (var setter in settersToRemove)
{
style.Setters.Remove(setter);
}

// Add New font setter
style.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
style.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
style.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
style.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));

// Set caret brush (retain existing logic)
var caretBrushPropertyValue = style.Setters.OfType<Setter>().Any(x => x.Property.Name == "CaretBrush");
var foregroundPropertyValue = style.Setters.OfType<Setter>().Where(x => x.Property.Name == "Foreground")
.Select(x => x.Value).FirstOrDefault();
if (!caretBrushPropertyValue && foregroundPropertyValue != null)
style.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, foregroundPropertyValue));
}
else
{
var settersToRemove = style.Setters
.OfType<Setter>()
.Where(setter =>
setter.Property == TextBlock.FontFamilyProperty ||
setter.Property == TextBlock.FontStyleProperty ||
setter.Property == TextBlock.FontWeightProperty ||
setter.Property == TextBlock.FontStretchProperty)
.ToList();

foreach (var setter in settersToRemove)
{
style.Setters.Remove(setter);
}

style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, fontFamily));
style.Setters.Add(new Setter(TextBlock.FontStyleProperty, fontStyle));
style.Setters.Add(new Setter(TextBlock.FontWeightProperty, fontWeight));
style.Setters.Add(new Setter(TextBlock.FontStretchProperty, fontStretch));
}
}

private ResourceDictionary GetThemeResourceDictionary(string theme)
{
var uri = GetThemePath(theme);
Expand All @@ -128,22 +270,22 @@ private ResourceDictionary GetResourceDictionary(string theme)
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.QueryBoxFontWeight);
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.QueryBoxFontStretch);

queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, fontFamily));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, fontStyle));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, fontWeight));
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, fontStretch));
queryBoxStyle.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
queryBoxStyle.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
queryBoxStyle.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
queryBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));

var caretBrushPropertyValue = queryBoxStyle.Setters.OfType<Setter>().Any(x => x.Property.Name == "CaretBrush");
var foregroundPropertyValue = queryBoxStyle.Setters.OfType<Setter>().Where(x => x.Property.Name == "Foreground")
.Select(x => x.Value).FirstOrDefault();
if (!caretBrushPropertyValue && foregroundPropertyValue != null) //otherwise BaseQueryBoxStyle will handle styling
queryBoxStyle.Setters.Add(new Setter(TextBox.CaretBrushProperty, foregroundPropertyValue));
queryBoxStyle.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, foregroundPropertyValue));

// Query suggestion box's font style is aligned with query box
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, fontFamily));
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, fontStyle));
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, fontWeight));
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, fontStretch));
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
}

if (dict["ItemTitleStyle"] is Style resultItemStyle &&
Expand Down Expand Up @@ -180,7 +322,7 @@ private ResourceDictionary GetResourceDictionary(string theme)
/* Ignore Theme Window Width and use setting */
var windowStyle = dict["WindowStyle"] as Style;
var width = _settings.WindowSize;
windowStyle.Setters.Add(new Setter(Window.WidthProperty, width));
windowStyle.Setters.Add(new Setter(FrameworkElement.WidthProperty, width));
return dict;
}

Expand Down Expand Up @@ -265,11 +407,12 @@ public bool ChangeTheme(string theme = null)
try
{
if (string.IsNullOrEmpty(path))
throw new DirectoryNotFoundException("Theme path can't be found <{path}>");
throw new DirectoryNotFoundException($"Theme path can't be found <{path}>");

// reload all resources even if the theme itself hasn't changed in order to pickup changes
// to things like fonts
UpdateResourceDictionary(GetResourceDictionary(theme));
// Retrieve theme resource – always use the resource with font settings applied.
var resourceDict = GetResourceDictionary(theme);

UpdateResourceDictionary(resourceDict);

_settings.Theme = theme;

Expand All @@ -280,10 +423,11 @@ public bool ChangeTheme(string theme = null)
}

BlurEnabled = IsBlurTheme();
//if (_settings.UseDropShadowEffect)
// AddDropShadowEffectToCurrentTheme();
//Win32Helper.SetBlurForWindow(Application.Current.MainWindow, BlurEnabled);
_ = SetBlurForWindowAsync();

// Can only apply blur but here also apply drop shadow effect to avoid possible drop shadow effect issues
_ = RefreshFrameAsync();

return true;
}
catch (DirectoryNotFoundException)
{
Expand All @@ -305,7 +449,6 @@ public bool ChangeTheme(string theme = null)
}
return false;
}
return true;
}

#endregion
Expand Down Expand Up @@ -481,17 +624,14 @@ await Application.Current.Dispatcher.InvokeAsync(() =>

private void SetBlurForWindow(string theme, BackdropTypes backdropType)
{
var dict = GetThemeResourceDictionary(theme);
if (dict == null)
return;
var dict = GetResourceDictionary(theme);
if (dict == null) return;

var windowBorderStyle = dict.Contains("WindowBorderStyle") ? dict["WindowBorderStyle"] as Style : null;
if (windowBorderStyle == null)
return;
if (windowBorderStyle == null) return;

Window mainWindow = Application.Current.MainWindow;
if (mainWindow == null)
return;
var mainWindow = Application.Current.MainWindow;
if (mainWindow == null) return;

// Check if the theme supports blur
bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ public BackdropTypes BackdropType

Settings.BackdropType = value;

// Can only apply blur because drop shadow effect is not supported with backdrop
// So drop shadow effect has been disabled
_ = _theme.SetBlurForWindowAsync();

OnPropertyChanged(nameof(IsDropShadowEnabled));
Expand Down Expand Up @@ -342,7 +344,7 @@ public FontFamily SelectedQueryBoxFont
set
{
Settings.QueryBoxFont = value.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand All @@ -364,7 +366,7 @@ public FamilyTypeface SelectedQueryBoxFontFaces
Settings.QueryBoxFontStretch = value.Stretch.ToString();
Settings.QueryBoxFontWeight = value.Weight.ToString();
Settings.QueryBoxFontStyle = value.Style.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand All @@ -386,7 +388,7 @@ public FontFamily SelectedResultFont
set
{
Settings.ResultFont = value.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand All @@ -408,7 +410,7 @@ public FamilyTypeface SelectedResultFontFaces
Settings.ResultFontStretch = value.Stretch.ToString();
Settings.ResultFontWeight = value.Weight.ToString();
Settings.ResultFontStyle = value.Style.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand All @@ -432,7 +434,7 @@ public FontFamily SelectedResultSubFont
set
{
Settings.ResultSubFont = value.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand All @@ -453,7 +455,7 @@ public FamilyTypeface SelectedResultSubFontFaces
Settings.ResultSubFontStretch = value.Stretch.ToString();
Settings.ResultSubFontWeight = value.Weight.ToString();
Settings.ResultSubFontStyle = value.Style.ToString();
_theme.ChangeTheme();
_theme.UpdateFonts();
}
}

Expand Down
Loading
Loading