Skip to content

Commit a544aa2

Browse files
committed
Added feature to use your own font in the app
1 parent bb574c7 commit a544aa2

File tree

5 files changed

+205
-3
lines changed

5 files changed

+205
-3
lines changed

Bloxstrap/Models/Persistable/Settings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class Settings
2929
public bool DisableAnimations { get; set; } = false;
3030
public bool DisableHardwareAcceleration { get; set; } = false;
3131
public bool HighPriority { get; set; } = false;
32+
public string? CustomFontPath { get; set; } = null;
3233
public bool EnableAnalytics { get; set; } = false;
3334
public bool UpdateRoblox { get; set; } = true;
3435
public bool MultiInstanceLaunching { get; set; } = false;

Bloxstrap/UI/Elements/Settings/MainWindow.xaml.cs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
using System.Windows;
77
using System.Windows.Controls;
88

9+
using Microsoft.Win32;
10+
using System.Windows.Media;
11+
using System.IO;
12+
using System.Collections.Generic;
13+
914
using Wpf.Ui.Controls;
1015
using Wpf.Ui.Controls.Interfaces;
1116
using Wpf.Ui.Mvvm.Contracts;
@@ -28,6 +33,8 @@ public partial class MainWindow : INavigationWindow
2833
public static List<string> DefaultNavigationOrder { get; private set; } = new();
2934
public static List<string> DefaultFooterOrder { get; private set; } = new();
3035

36+
private System.Windows.Media.FontFamily? userSelectedFontFamily;
37+
3138
public MainWindow(bool showAlreadyRunningWarning)
3239
{
3340
var viewModel = new MainWindowViewModel();
@@ -47,7 +54,7 @@ public MainWindow(bool showAlreadyRunningWarning)
4754
LoadState();
4855

4956
var allItems = RootNavigation.Items.OfType<NavigationItem>().ToList();
50-
var allFooters = RootNavigation.Footer?.OfType<NavigationItem>().ToList() ?? new System.Collections.Generic.List<NavigationItem>();
57+
var allFooters = RootNavigation.Footer?.OfType<NavigationItem>().ToList() ?? new List<NavigationItem>();
5158

5259
MainNavigationItems.Clear();
5360
FooterNavigationItems.Clear();
@@ -80,7 +87,6 @@ void SaveNavigation(object? sender, RoutedNavigationEventArgs? e)
8087
}
8188
}
8289

83-
8490
private void CacheDefaultNavigationOrder()
8591
{
8692
DefaultNavigationOrder = MainNavigationItems
@@ -205,6 +211,70 @@ public void ResetNavigationToDefault()
205211
App.State.Save();
206212
}
207213

214+
private void SelectFontFile_Click(object sender, RoutedEventArgs e)
215+
{
216+
var dlg = new OpenFileDialog
217+
{
218+
Filter = "Font files (*.ttf;*.otf)|*.ttf;*.otf|All files (*.*)|*.*"
219+
};
220+
221+
if (dlg.ShowDialog() == true)
222+
{
223+
var fontPath = dlg.FileName;
224+
try
225+
{
226+
userSelectedFontFamily = LoadFontFromFile(fontPath);
227+
if (userSelectedFontFamily != null)
228+
{
229+
ApplyFontGlobally(userSelectedFontFamily);
230+
System.Windows.MessageBox.Show($"Font '{userSelectedFontFamily.Source}' applied successfully.");
231+
}
232+
else
233+
{
234+
System.Windows.MessageBox.Show("Failed to load font.");
235+
}
236+
}
237+
catch (Exception ex)
238+
{
239+
System.Windows.MessageBox.Show($"Error loading font: {ex.Message}");
240+
}
241+
}
242+
}
243+
244+
private System.Windows.Media.FontFamily? LoadFontFromFile(string fontFilePath)
245+
{
246+
if (!File.Exists(fontFilePath))
247+
throw new FileNotFoundException("Font file not found.", fontFilePath);
248+
249+
string tempFontsFolder = Path.Combine(Path.GetTempPath(), "BloxstrapFonts");
250+
Directory.CreateDirectory(tempFontsFolder);
251+
252+
string destFontPath = Path.Combine(tempFontsFolder, Path.GetFileName(fontFilePath));
253+
File.Copy(fontFilePath, destFontPath, overwrite: true);
254+
255+
Uri fontDirectoryUri = new Uri(Path.GetDirectoryName(destFontPath) + Path.DirectorySeparatorChar, UriKind.Absolute);
256+
257+
ICollection<System.Windows.Media.FontFamily> fontFamilies = Fonts.GetFontFamilies(fontDirectoryUri);
258+
259+
if (fontFamilies == null || fontFamilies.Count == 0)
260+
return null;
261+
262+
return fontFamilies.FirstOrDefault();
263+
}
264+
265+
private void ApplyFontGlobally(System.Windows.Media.FontFamily fontFamily)
266+
{
267+
Application.Current.Resources["{x:Static SystemFonts.MessageFontFamilyKey}"] = fontFamily;
268+
269+
this.FontFamily = fontFamily;
270+
271+
foreach (Window window in Application.Current.Windows)
272+
{
273+
window.FontFamily = fontFamily;
274+
}
275+
}
276+
277+
208278
public void LoadState()
209279
{
210280
if (_state.Left > SystemParameters.VirtualScreenWidth)

Bloxstrap/UI/Elements/Settings/Pages/AppearancePage.xaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@
3939
<ComboBox Width="200" Padding="10,5,10,5" ItemsSource="{Binding Languages, Mode=OneTime}" Text="{Binding SelectedLanguage, Mode=TwoWay}" />
4040
</controls:OptionControl>
4141

42+
<controls:OptionControl
43+
Header="Custom Font"
44+
Description="Choose a custom font file to override the default UI font.">
45+
46+
<StackPanel>
47+
<ui:Button
48+
Content="Choose Font"
49+
Icon="DocumentAdd16"
50+
Command="{Binding ManageCustomFontCommand}"
51+
CommandParameter="Choose"
52+
Visibility="{Binding ChooseCustomFontVisibility, Mode=OneWay}" />
53+
<ui:Button
54+
Content="Remove Font"
55+
Icon="Delete16"
56+
Appearance="Danger"
57+
Command="{Binding ManageCustomFontCommand}"
58+
CommandParameter="Remove"
59+
Visibility="{Binding DeleteCustomFontVisibility, Mode=OneWay}" />
60+
</StackPanel>
61+
</controls:OptionControl>
62+
4263
<ui:CardExpander Margin="0,8,0,0" IsExpanded="False">
4364
<ui:CardExpander.Header>
4465
<Grid>

Bloxstrap/UI/Elements/Settings/Pages/ChannelPage.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171

7272
<controls:OptionControl
7373
Header="High Priority"
74-
Description="Runs Roblox with high CPU priority.">
74+
Description="Runs Roblox with high CPU priority using Task Manager.">
7575
<ui:ToggleSwitch IsChecked="{Binding HighPriority, Mode=TwoWay}" />
7676
</controls:OptionControl>
7777

Bloxstrap/UI/ViewModels/Settings/AppearanceViewModel.cs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Bloxstrap.UI.Elements.Editor;
1212
using Bloxstrap.UI.Elements.Dialogs;
1313
using ICSharpCode.SharpZipLib.Zip;
14+
using System.Windows.Media;
1415

1516
namespace Bloxstrap.UI.ViewModels.Settings
1617
{
@@ -26,6 +27,7 @@ public class AppearanceViewModel : NotifyPropertyChangedViewModel
2627
public ICommand RenameCustomThemeCommand => new RelayCommand(RenameCustomTheme);
2728
public ICommand EditCustomThemeCommand => new RelayCommand(EditCustomTheme);
2829
public ICommand ExportCustomThemeCommand => new RelayCommand(ExportCustomTheme);
30+
public ICommand ManageCustomFontCommand => new RelayCommand<string>(ManageCustomFont!);
2931

3032
private void PreviewBootstrapper()
3133
{
@@ -40,6 +42,113 @@ private void PreviewBootstrapper()
4042
dialog.ShowBootstrapper();
4143
}
4244

45+
private bool _isCustomFontApplied;
46+
47+
public Visibility ChooseCustomFontVisibility =>
48+
_isCustomFontApplied ? Visibility.Collapsed : Visibility.Visible;
49+
50+
public Visibility DeleteCustomFontVisibility =>
51+
_isCustomFontApplied ? Visibility.Visible : Visibility.Collapsed;
52+
53+
private void UpdateFontVisibility()
54+
{
55+
OnPropertyChanged(nameof(ChooseCustomFontVisibility));
56+
OnPropertyChanged(nameof(DeleteCustomFontVisibility));
57+
}
58+
59+
private void ManageCustomFont(string action)
60+
{
61+
if (action == "Choose")
62+
{
63+
var dialog = new OpenFileDialog
64+
{
65+
Filter = "Font files (*.ttf;*.otf)|*.ttf;*.otf|All files (*.*)|*.*"
66+
};
67+
68+
if (dialog.ShowDialog() == true)
69+
{
70+
string fontPath = dialog.FileName;
71+
72+
try
73+
{
74+
var fontFamily = LoadFontFromFile(fontPath);
75+
if (fontFamily != null)
76+
{
77+
ApplyFontGlobally(fontFamily);
78+
_isCustomFontApplied = true;
79+
App.Settings.Prop.CustomFontPath = fontPath;
80+
App.Settings.Save();
81+
UpdateFontVisibility();
82+
}
83+
}
84+
catch (Exception ex)
85+
{
86+
MessageBox.Show($"Failed to load font: {ex.Message}", "Font Error", MessageBoxButton.OK, MessageBoxImage.Error);
87+
}
88+
}
89+
}
90+
else if (action == "Remove")
91+
{
92+
var defaultFont = new System.Windows.Media.FontFamily("Segoe UI");
93+
ApplyFontGlobally(defaultFont);
94+
_isCustomFontApplied = false;
95+
App.Settings.Prop.CustomFontPath = null;
96+
App.Settings.Save();
97+
UpdateFontVisibility();
98+
}
99+
}
100+
101+
private System.Windows.Media.FontFamily? LoadFontFromFile(string fontFilePath)
102+
{
103+
if (!File.Exists(fontFilePath))
104+
return null;
105+
106+
string tempFontsFolder = Path.Combine(Path.GetTempPath(), "BloxstrapFonts");
107+
Directory.CreateDirectory(tempFontsFolder);
108+
109+
string destFontPath = Path.Combine(tempFontsFolder, Path.GetFileName(fontFilePath));
110+
File.Copy(fontFilePath, destFontPath, overwrite: true);
111+
112+
var fontDirectoryUri = new Uri(Path.GetDirectoryName(destFontPath) + Path.DirectorySeparatorChar);
113+
var fontFamilies = Fonts.GetFontFamilies(fontDirectoryUri);
114+
115+
return fontFamilies.FirstOrDefault();
116+
}
117+
118+
private void ApplyFontGlobally(System.Windows.Media.FontFamily fontFamily)
119+
{
120+
Application.Current.Resources[SystemFonts.MessageFontFamilyKey] = fontFamily;
121+
122+
foreach (Window window in Application.Current.Windows)
123+
{
124+
window.FontFamily = fontFamily;
125+
}
126+
}
127+
128+
private void ApplySavedCustomFont()
129+
{
130+
string? savedFontPath = App.Settings.Prop.CustomFontPath;
131+
132+
if (!string.IsNullOrWhiteSpace(savedFontPath) && File.Exists(savedFontPath))
133+
{
134+
try
135+
{
136+
var font = LoadFontFromFile(savedFontPath);
137+
if (font != null)
138+
{
139+
ApplyFontGlobally(font);
140+
_isCustomFontApplied = true;
141+
}
142+
}
143+
catch (Exception ex)
144+
{
145+
App.Logger.WriteLine("AppearanceViewModel", $"Failed to load saved font: {ex}");
146+
}
147+
}
148+
149+
UpdateFontVisibility();
150+
}
151+
43152
private void BrowseCustomIconLocation()
44153
{
45154
var dialog = new OpenFileDialog
@@ -65,6 +174,7 @@ public AppearanceViewModel(Page page)
65174
ThemeIcons.Add(new ThemeEntry { IconType = (Theme)entry });
66175

67176
PopulateCustomThemes();
177+
ApplySavedCustomFont();
68178
}
69179

70180
public IEnumerable<Theme> Themes { get; } = Enum.GetValues(typeof(Theme)).Cast<Theme>();

0 commit comments

Comments
 (0)