diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs new file mode 100644 index 000000000..ffcbceb11 --- /dev/null +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -0,0 +1,371 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Flow.Launcher.Core.Resource; +using Flow.Launcher.Helper; +using Flow.Launcher.Infrastructure; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; +using Flow.Launcher.ViewModel; + +namespace Flow.Launcher.SettingPages.ViewModels; + +public class SettingsPaneThemeViewModel : BaseModel +{ + private CultureInfo Culture => CultureInfo.DefaultThreadCurrentCulture; + + public Settings Settings { get; } + + public static string LinkHowToCreateTheme => @"https://flowlauncher.com/docs/#/how-to-create-a-theme"; + public static string LinkThemeGallery => "https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438"; + + public string SelectedTheme + { + get => Settings.Theme; + set + { + ThemeManager.Instance.ChangeTheme(value); + + if (ThemeManager.Instance.BlurEnabled && Settings.UseDropShadowEffect) + DropShadowEffect = false; + } + } + + public bool DropShadowEffect + { + get => Settings.UseDropShadowEffect; + set + { + if (ThemeManager.Instance.BlurEnabled && value) + { + MessageBox.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); + return; + } + + if (value) + { + ThemeManager.Instance.AddDropShadowEffectToCurrentTheme(); + } + else + { + ThemeManager.Instance.RemoveDropShadowEffectFromCurrentTheme(); + } + + Settings.UseDropShadowEffect = value; + } + } + + public List Themes => + ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension).ToList(); + + + public class ColorScheme + { + public string Display { get; set; } + public ColorSchemes Value { get; set; } + } + + public List ColorSchemes + { + get + { + List modes = new List(); + var enums = (ColorSchemes[])Enum.GetValues(typeof(ColorSchemes)); + foreach (var e in enums) + { + var key = $"ColorScheme{e}"; + var display = InternationalizationManager.Instance.GetTranslation(key); + var m = new ColorScheme { Display = display, Value = e, }; + modes.Add(m); + } + + return modes; + } + } + + public List TimeFormatList { get; } = new() + { + "h:mm", + "hh:mm", + "H:mm", + "HH:mm", + "tt h:mm", + "tt hh:mm", + "h:mm tt", + "hh:mm tt", + "hh:mm:ss tt", + "HH:mm:ss" + }; + + public List DateFormatList { get; } = new() + { + "MM'/'dd dddd", + "MM'/'dd ddd", + "MM'/'dd", + "MM'-'dd", + "MMMM', 'dd", + "dd'/'MM", + "dd'-'MM", + "ddd MM'/'dd", + "dddd MM'/'dd", + "dddd", + "ddd dd'/'MM", + "dddd dd'/'MM", + "dddd dd', 'MMMM", + "dd', 'MMMM" + }; + + public string TimeFormat + { + get => Settings.TimeFormat; + set => Settings.TimeFormat = value; + } + + public string DateFormat + { + get => Settings.DateFormat; + set => Settings.DateFormat = value; + } + + public string ClockText => DateTime.Now.ToString(TimeFormat, Culture); + + public string DateText => DateTime.Now.ToString(DateFormat, Culture); + + public double WindowWidthSize + { + get => Settings.WindowSize; + set => Settings.WindowSize = value; + } + + public bool UseGlyphIcons + { + get => Settings.UseGlyphIcons; + set => Settings.UseGlyphIcons = value; + } + + public bool UseAnimation + { + get => Settings.UseAnimation; + set => Settings.UseAnimation = value; + } + + public class AnimationSpeed + { + public string Display { get; set; } + public AnimationSpeeds Value { get; set; } + } + + public List AnimationSpeeds + { + get + { + List speeds = new List(); + var enums = (AnimationSpeeds[])Enum.GetValues(typeof(AnimationSpeeds)); + foreach (var e in enums) + { + var key = $"AnimationSpeed{e}"; + var display = InternationalizationManager.Instance.GetTranslation(key); + var m = new AnimationSpeed { Display = display, Value = e, }; + speeds.Add(m); + } + + return speeds; + } + } + + public bool UseSound + { + get => Settings.UseSound; + set => Settings.UseSound = value; + } + + public double SoundEffectVolume + { + get => Settings.SoundVolume; + set => Settings.SoundVolume = value; + } + + public bool UseClock + { + get => Settings.UseClock; + set => Settings.UseClock = value; + } + + public bool UseDate + { + get => Settings.UseDate; + set => Settings.UseDate = value; + } + + public Brush PreviewBackground + { + get + { + var wallpaper = WallpaperPathRetrieval.GetWallpaperPath(); + if (wallpaper is not null && File.Exists(wallpaper)) + { + var memStream = new MemoryStream(File.ReadAllBytes(wallpaper)); + var bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.StreamSource = memStream; + bitmap.DecodePixelWidth = 800; + bitmap.DecodePixelHeight = 600; + bitmap.EndInit(); + return new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill }; + } + + var wallpaperColor = WallpaperPathRetrieval.GetWallpaperColor(); + return new SolidColorBrush(wallpaperColor); + } + } + + public ResultsViewModel PreviewResults + { + get + { + var results = new List + { + new Result + { + Title = InternationalizationManager.Instance.GetTranslation("SampleTitleExplorer"), + SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleExplorer"), + IcoPath = Path.Combine( + Constant.ProgramDirectory, + @"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png" + ) + }, + new Result + { + Title = InternationalizationManager.Instance.GetTranslation("SampleTitleWebSearch"), + SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleWebSearch"), + IcoPath = Path.Combine( + Constant.ProgramDirectory, + @"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png" + ) + }, + new Result + { + Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProgram"), + SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProgram"), + IcoPath = Path.Combine( + Constant.ProgramDirectory, + @"Plugins\Flow.Launcher.Plugin.Program\Images\program.png" + ) + }, + new Result + { + Title = InternationalizationManager.Instance.GetTranslation("SampleTitleProcessKiller"), + SubTitle = InternationalizationManager.Instance.GetTranslation("SampleSubTitleProcessKiller"), + IcoPath = Path.Combine( + Constant.ProgramDirectory, + @"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png" + ) + } + }; + var vm = new ResultsViewModel(Settings); + vm.AddResults(results, "PREVIEW"); + return vm; + } + } + + public FontFamily SelectedQueryBoxFont + { + get + { + var fontExists = Fonts.SystemFontFamilies.Any( + fontFamily => + fontFamily.FamilyNames.Values != null && + fontFamily.FamilyNames.Values.Contains(Settings.QueryBoxFont) + ); + + return fontExists switch + { + true => new FontFamily(Settings.QueryBoxFont), + _ => new FontFamily("Segoe UI") + }; + } + set + { + Settings.QueryBoxFont = value.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public FamilyTypeface SelectedQueryBoxFontFaces + { + get + { + var typeface = SyntaxSugars.CallOrRescueDefault( + () => SelectedQueryBoxFont.ConvertFromInvariantStringsOrNormal( + Settings.QueryBoxFontStyle, + Settings.QueryBoxFontWeight, + Settings.QueryBoxFontStretch + ) + ); + return typeface; + } + set + { + Settings.QueryBoxFontStretch = value.Stretch.ToString(); + Settings.QueryBoxFontWeight = value.Weight.ToString(); + Settings.QueryBoxFontStyle = value.Style.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public FontFamily SelectedResultFont + { + get + { + var fontExists = Fonts.SystemFontFamilies.Any( + fontFamily => + fontFamily.FamilyNames.Values != null && + fontFamily.FamilyNames.Values.Contains(Settings.ResultFont) + ); + return fontExists switch + { + true => new FontFamily(Settings.ResultFont), + _ => new FontFamily("Segoe UI") + }; + } + set + { + Settings.ResultFont = value.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public FamilyTypeface SelectedResultFontFaces + { + get + { + var typeface = SyntaxSugars.CallOrRescueDefault( + () => SelectedResultFont.ConvertFromInvariantStringsOrNormal( + Settings.ResultFontStyle, + Settings.ResultFontWeight, + Settings.ResultFontStretch + ) + ); + return typeface; + } + set + { + Settings.ResultFontStretch = value.Stretch.ToString(); + Settings.ResultFontWeight = value.Weight.ToString(); + Settings.ResultFontStyle = value.Style.ToString(); + ThemeManager.Instance.ChangeTheme(Settings.Theme); + } + } + + public string ThemeImage => Constant.QueryTextBoxIconImagePath; + + public SettingsPaneThemeViewModel(Settings settings) + { + Settings = settings; + } +} diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml index 8dc485134..f56367f96 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml @@ -5,11 +5,12 @@ xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:flowlauncher="clr-namespace:Flow.Launcher" - xmlns:local="clr-namespace:Flow.Launcher.SettingPages.Views" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" + xmlns:viewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" Title="Theme" + d:DataContext="{d:DesignInstance viewModels:SettingsPaneThemeViewModel}" d:DesignHeight="450" d:DesignWidth="800" Style="{DynamicResource SettingPageBasic}" @@ -202,8 +203,10 @@