Skip to content

Commit 7c418a6

Browse files
authored
Merge pull request #3377 from onesounds/050322-FixFontSelectFunction
Fix font select function
2 parents e5ee856 + d212e0e commit 7c418a6

File tree

4 files changed

+189
-52
lines changed

4 files changed

+189
-52
lines changed

Flow.Launcher.Core/Resource/Theme.cs

+181-41
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading.Tasks;
77
using System.Windows;
88
using System.Windows.Controls;
9+
using System.Windows.Controls.Primitives;
910
using System.Windows.Markup;
1011
using System.Windows.Media;
1112
using System.Windows.Media.Effects;
@@ -16,7 +17,6 @@
1617
using Flow.Launcher.Infrastructure.UserSettings;
1718
using Flow.Launcher.Plugin;
1819
using Microsoft.Win32;
19-
using TextBox = System.Windows.Controls.TextBox;
2020

2121
namespace Flow.Launcher.Core.Resource
2222
{
@@ -56,20 +56,23 @@ public Theme(IPublicAPI publicAPI, Settings settings)
5656
MakeSureThemeDirectoriesExist();
5757

5858
var dicts = Application.Current.Resources.MergedDictionaries;
59-
_oldResource = dicts.First(d =>
59+
_oldResource = dicts.FirstOrDefault(d =>
6060
{
61-
if (d.Source == null)
62-
return false;
61+
if (d.Source == null) return false;
6362

6463
var p = d.Source.AbsolutePath;
65-
var dir = Path.GetDirectoryName(p).NonNull();
66-
var info = new DirectoryInfo(dir);
67-
var f = info.Name;
68-
var e = Path.GetExtension(p);
69-
var found = f == Folder && e == Extension;
70-
return found;
64+
return p.Contains(Folder) && Path.GetExtension(p) == Extension;
7165
});
72-
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
66+
67+
if (_oldResource != null)
68+
{
69+
_oldTheme = Path.GetFileNameWithoutExtension(_oldResource.Source.AbsolutePath);
70+
}
71+
else
72+
{
73+
Log.Error("Current theme resource not found. Initializing with default theme.");
74+
_oldTheme = Constant.DefaultTheme;
75+
};
7376
}
7477

7578
#endregion
@@ -98,13 +101,152 @@ private void MakeSureThemeDirectoriesExist()
98101

99102
private void UpdateResourceDictionary(ResourceDictionary dictionaryToUpdate)
100103
{
101-
var dicts = Application.Current.Resources.MergedDictionaries;
104+
// Add new resources
105+
if (!Application.Current.Resources.MergedDictionaries.Contains(dictionaryToUpdate))
106+
{
107+
Application.Current.Resources.MergedDictionaries.Add(dictionaryToUpdate);
108+
}
109+
110+
// Remove old resources
111+
if (_oldResource != null && _oldResource != dictionaryToUpdate &&
112+
Application.Current.Resources.MergedDictionaries.Contains(_oldResource))
113+
{
114+
Application.Current.Resources.MergedDictionaries.Remove(_oldResource);
115+
}
102116

103-
dicts.Remove(_oldResource);
104-
dicts.Add(dictionaryToUpdate);
105117
_oldResource = dictionaryToUpdate;
106118
}
107119

120+
/// <summary>
121+
/// Updates only the font settings and refreshes the UI.
122+
/// </summary>
123+
public void UpdateFonts()
124+
{
125+
try
126+
{
127+
// Load a ResourceDictionary for the specified theme.
128+
var themeName = GetCurrentTheme();
129+
var dict = GetThemeResourceDictionary(themeName);
130+
131+
// Apply font settings to the theme resource.
132+
ApplyFontSettings(dict);
133+
UpdateResourceDictionary(dict);
134+
135+
// Must apply blur and drop shadow effects
136+
_ = RefreshFrameAsync();
137+
}
138+
catch (Exception e)
139+
{
140+
Log.Exception("Error occurred while updating theme fonts", e);
141+
}
142+
}
143+
144+
/// <summary>
145+
/// Loads and applies font settings to the theme resource.
146+
/// </summary>
147+
private void ApplyFontSettings(ResourceDictionary dict)
148+
{
149+
if (dict["QueryBoxStyle"] is Style queryBoxStyle &&
150+
dict["QuerySuggestionBoxStyle"] is Style querySuggestionBoxStyle)
151+
{
152+
var fontFamily = new FontFamily(_settings.QueryBoxFont);
153+
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.QueryBoxFontStyle);
154+
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.QueryBoxFontWeight);
155+
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.QueryBoxFontStretch);
156+
157+
SetFontProperties(queryBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, true);
158+
SetFontProperties(querySuggestionBoxStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
159+
}
160+
161+
if (dict["ItemTitleStyle"] is Style resultItemStyle &&
162+
dict["ItemTitleSelectedStyle"] is Style resultItemSelectedStyle &&
163+
dict["ItemHotkeyStyle"] is Style resultHotkeyItemStyle &&
164+
dict["ItemHotkeySelectedStyle"] is Style resultHotkeyItemSelectedStyle)
165+
{
166+
var fontFamily = new FontFamily(_settings.ResultFont);
167+
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultFontStyle);
168+
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultFontWeight);
169+
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultFontStretch);
170+
171+
SetFontProperties(resultItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
172+
SetFontProperties(resultItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
173+
SetFontProperties(resultHotkeyItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
174+
SetFontProperties(resultHotkeyItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
175+
}
176+
177+
if (dict["ItemSubTitleStyle"] is Style resultSubItemStyle &&
178+
dict["ItemSubTitleSelectedStyle"] is Style resultSubItemSelectedStyle)
179+
{
180+
var fontFamily = new FontFamily(_settings.ResultSubFont);
181+
var fontStyle = FontHelper.GetFontStyleFromInvariantStringOrNormal(_settings.ResultSubFontStyle);
182+
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.ResultSubFontWeight);
183+
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.ResultSubFontStretch);
184+
185+
SetFontProperties(resultSubItemStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
186+
SetFontProperties(resultSubItemSelectedStyle, fontFamily, fontStyle, fontWeight, fontStretch, false);
187+
}
188+
}
189+
190+
/// <summary>
191+
/// Applies font properties to a Style.
192+
/// </summary>
193+
private static void SetFontProperties(Style style, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, bool isTextBox)
194+
{
195+
// Remove existing font-related setters
196+
if (isTextBox)
197+
{
198+
// First, find the setters to remove and store them in a list
199+
var settersToRemove = style.Setters
200+
.OfType<Setter>()
201+
.Where(setter =>
202+
setter.Property == Control.FontFamilyProperty ||
203+
setter.Property == Control.FontStyleProperty ||
204+
setter.Property == Control.FontWeightProperty ||
205+
setter.Property == Control.FontStretchProperty)
206+
.ToList();
207+
208+
// Remove each found setter one by one
209+
foreach (var setter in settersToRemove)
210+
{
211+
style.Setters.Remove(setter);
212+
}
213+
214+
// Add New font setter
215+
style.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
216+
style.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
217+
style.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
218+
style.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
219+
220+
// Set caret brush (retain existing logic)
221+
var caretBrushPropertyValue = style.Setters.OfType<Setter>().Any(x => x.Property.Name == "CaretBrush");
222+
var foregroundPropertyValue = style.Setters.OfType<Setter>().Where(x => x.Property.Name == "Foreground")
223+
.Select(x => x.Value).FirstOrDefault();
224+
if (!caretBrushPropertyValue && foregroundPropertyValue != null)
225+
style.Setters.Add(new Setter(TextBoxBase.CaretBrushProperty, foregroundPropertyValue));
226+
}
227+
else
228+
{
229+
var settersToRemove = style.Setters
230+
.OfType<Setter>()
231+
.Where(setter =>
232+
setter.Property == TextBlock.FontFamilyProperty ||
233+
setter.Property == TextBlock.FontStyleProperty ||
234+
setter.Property == TextBlock.FontWeightProperty ||
235+
setter.Property == TextBlock.FontStretchProperty)
236+
.ToList();
237+
238+
foreach (var setter in settersToRemove)
239+
{
240+
style.Setters.Remove(setter);
241+
}
242+
243+
style.Setters.Add(new Setter(TextBlock.FontFamilyProperty, fontFamily));
244+
style.Setters.Add(new Setter(TextBlock.FontStyleProperty, fontStyle));
245+
style.Setters.Add(new Setter(TextBlock.FontWeightProperty, fontWeight));
246+
style.Setters.Add(new Setter(TextBlock.FontStretchProperty, fontStretch));
247+
}
248+
}
249+
108250
private ResourceDictionary GetThemeResourceDictionary(string theme)
109251
{
110252
var uri = GetThemePath(theme);
@@ -128,22 +270,22 @@ private ResourceDictionary GetResourceDictionary(string theme)
128270
var fontWeight = FontHelper.GetFontWeightFromInvariantStringOrNormal(_settings.QueryBoxFontWeight);
129271
var fontStretch = FontHelper.GetFontStretchFromInvariantStringOrNormal(_settings.QueryBoxFontStretch);
130272

131-
queryBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, fontFamily));
132-
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, fontStyle));
133-
queryBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, fontWeight));
134-
queryBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, fontStretch));
273+
queryBoxStyle.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
274+
queryBoxStyle.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
275+
queryBoxStyle.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
276+
queryBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
135277

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

142284
// Query suggestion box's font style is aligned with query box
143-
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontFamilyProperty, fontFamily));
144-
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontStyleProperty, fontStyle));
145-
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontWeightProperty, fontWeight));
146-
querySuggestionBoxStyle.Setters.Add(new Setter(TextBox.FontStretchProperty, fontStretch));
285+
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontFamilyProperty, fontFamily));
286+
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontStyleProperty, fontStyle));
287+
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontWeightProperty, fontWeight));
288+
querySuggestionBoxStyle.Setters.Add(new Setter(Control.FontStretchProperty, fontStretch));
147289
}
148290

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

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

270-
// reload all resources even if the theme itself hasn't changed in order to pickup changes
271-
// to things like fonts
272-
UpdateResourceDictionary(GetResourceDictionary(theme));
412+
// Retrieve theme resource – always use the resource with font settings applied.
413+
var resourceDict = GetResourceDictionary(theme);
414+
415+
UpdateResourceDictionary(resourceDict);
273416

274417
_settings.Theme = theme;
275418

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

282425
BlurEnabled = IsBlurTheme();
283-
//if (_settings.UseDropShadowEffect)
284-
// AddDropShadowEffectToCurrentTheme();
285-
//Win32Helper.SetBlurForWindow(Application.Current.MainWindow, BlurEnabled);
286-
_ = SetBlurForWindowAsync();
426+
427+
// Can only apply blur but here also apply drop shadow effect to avoid possible drop shadow effect issues
428+
_ = RefreshFrameAsync();
429+
430+
return true;
287431
}
288432
catch (DirectoryNotFoundException)
289433
{
@@ -305,7 +449,6 @@ public bool ChangeTheme(string theme = null)
305449
}
306450
return false;
307451
}
308-
return true;
309452
}
310453

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

482625
private void SetBlurForWindow(string theme, BackdropTypes backdropType)
483626
{
484-
var dict = GetThemeResourceDictionary(theme);
485-
if (dict == null)
486-
return;
627+
var dict = GetResourceDictionary(theme);
628+
if (dict == null) return;
487629

488630
var windowBorderStyle = dict.Contains("WindowBorderStyle") ? dict["WindowBorderStyle"] as Style : null;
489-
if (windowBorderStyle == null)
490-
return;
631+
if (windowBorderStyle == null) return;
491632

492-
Window mainWindow = Application.Current.MainWindow;
493-
if (mainWindow == null)
494-
return;
633+
var mainWindow = Application.Current.MainWindow;
634+
if (mainWindow == null) return;
495635

496636
// Check if the theme supports blur
497637
bool hasBlur = dict.Contains("ThemeBlurEnabled") && dict["ThemeBlurEnabled"] is bool b && b;

Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs

+8-6
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ public BackdropTypes BackdropType
229229

230230
Settings.BackdropType = value;
231231

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

234236
OnPropertyChanged(nameof(IsDropShadowEnabled));
@@ -342,7 +344,7 @@ public FontFamily SelectedQueryBoxFont
342344
set
343345
{
344346
Settings.QueryBoxFont = value.ToString();
345-
_theme.ChangeTheme();
347+
_theme.UpdateFonts();
346348
}
347349
}
348350

@@ -364,7 +366,7 @@ public FamilyTypeface SelectedQueryBoxFontFaces
364366
Settings.QueryBoxFontStretch = value.Stretch.ToString();
365367
Settings.QueryBoxFontWeight = value.Weight.ToString();
366368
Settings.QueryBoxFontStyle = value.Style.ToString();
367-
_theme.ChangeTheme();
369+
_theme.UpdateFonts();
368370
}
369371
}
370372

@@ -386,7 +388,7 @@ public FontFamily SelectedResultFont
386388
set
387389
{
388390
Settings.ResultFont = value.ToString();
389-
_theme.ChangeTheme();
391+
_theme.UpdateFonts();
390392
}
391393
}
392394

@@ -408,7 +410,7 @@ public FamilyTypeface SelectedResultFontFaces
408410
Settings.ResultFontStretch = value.Stretch.ToString();
409411
Settings.ResultFontWeight = value.Weight.ToString();
410412
Settings.ResultFontStyle = value.Style.ToString();
411-
_theme.ChangeTheme();
413+
_theme.UpdateFonts();
412414
}
413415
}
414416

@@ -432,7 +434,7 @@ public FontFamily SelectedResultSubFont
432434
set
433435
{
434436
Settings.ResultSubFont = value.ToString();
435-
_theme.ChangeTheme();
437+
_theme.UpdateFonts();
436438
}
437439
}
438440

@@ -453,7 +455,7 @@ public FamilyTypeface SelectedResultSubFontFaces
453455
Settings.ResultSubFontStretch = value.Stretch.ToString();
454456
Settings.ResultSubFontWeight = value.Weight.ToString();
455457
Settings.ResultSubFontStyle = value.Style.ToString();
456-
_theme.ChangeTheme();
458+
_theme.UpdateFonts();
457459
}
458460
}
459461

0 commit comments

Comments
 (0)