From 8277cdd4b00f7a85c23a85578f39f46d7c8e5b1d Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Sat, 29 Dec 2018 23:04:11 -0500 Subject: [PATCH 1/5] Switch from 2-segment to 4-segment wallpaper schedule --- src/JsonConfig.cs | 2 + src/MainMenu.cs | 2 +- src/SystemThemeChanger.cs | 2 +- src/ThemeDialog.Designer.cs | 2 +- src/ThemeDialog.cs | 6 +- src/ThemeManager.cs | 4 +- src/WallpaperChangeScheduler.cs | 274 +++++++++++++++++--------------- src/WinDynamicDesktop.csproj | 4 +- src/packages.config | 2 +- src/themes/Mojave_Desert.json | 14 +- src/themes/Solar_Gradients.json | 18 ++- uwp/Package.appxmanifest | 2 +- 12 files changed, 181 insertions(+), 151 deletions(-) diff --git a/src/JsonConfig.cs b/src/JsonConfig.cs index 7a78853..3ec73d4 100644 --- a/src/JsonConfig.cs +++ b/src/JsonConfig.cs @@ -29,7 +29,9 @@ public class ThemeConfig public string imagesZipUri { get; set; } public string imageFilename { get; set; } public string imageCredits { get; set; } + public int[] sunriseImageList { get; set; } public int[] dayImageList { get; set; } + public int[] sunsetImageList { get; set; } public int[] nightImageList { get; set; } } diff --git a/src/MainMenu.cs b/src/MainMenu.cs index 2188e97..78e53c2 100644 --- a/src/MainMenu.cs +++ b/src/MainMenu.cs @@ -79,7 +79,7 @@ private static void ToggleDarkMode() JsonConfig.settings.darkMode = isEnabled; darkModeItem.Checked = isEnabled; - AppContext.wcsService.LoadImageLists(); + //AppContext.wcsService.LoadImageLists(); AppContext.wcsService.RunScheduler(); } diff --git a/src/SystemThemeChanger.cs b/src/SystemThemeChanger.cs index 597e1ef..259c2e9 100644 --- a/src/SystemThemeChanger.cs +++ b/src/SystemThemeChanger.cs @@ -44,7 +44,7 @@ public static void TryUpdateSystemTheme() return; } - bool darkTheme = !WallpaperChangeScheduler.isDayNow || JsonConfig.settings.darkMode; + bool darkTheme = WallpaperChangeScheduler.isNightNow || JsonConfig.settings.darkMode; RegistryKey themeKey = Registry.CurrentUser.OpenSubKey(registryThemeLocation, true); if (darkTheme) diff --git a/src/ThemeDialog.Designer.cs b/src/ThemeDialog.Designer.cs index c93dba5..f51b425 100644 --- a/src/ThemeDialog.Designer.cs +++ b/src/ThemeDialog.Designer.cs @@ -189,7 +189,7 @@ private void InitializeComponent() // // openFileDialog1 // - this.openFileDialog1.Filter = "Theme files|*.json;*.zip|All files|*.*"; + this.openFileDialog1.Filter = "Theme files|*.json;*.ddw;*.zip|All files|*.*"; this.openFileDialog1.InitialDirectory = "shell:Downloads"; this.openFileDialog1.Title = "Import Theme"; // diff --git a/src/ThemeDialog.cs b/src/ThemeDialog.cs index 03f1d38..5bbe894 100644 --- a/src/ThemeDialog.cs +++ b/src/ThemeDialog.cs @@ -26,7 +26,7 @@ public partial class ThemeDialog : Form public ThemeDialog() { InitializeComponent(); - + // TODO Handle 4 segments in image preview, generate thumbnails differently? this.FormClosing += OnFormClosing; listView1.ContextMenuStrip = contextMenuStrip1; listView1.ListViewItemSorter = new CompareByIndex(listView1); @@ -274,7 +274,7 @@ private void importButton_Click(object sender, EventArgs e) { return; } - else if (Path.GetExtension(themePath) == ".zip") + else if (Path.GetExtension(themePath) != ".json") { LoadImportedTheme(); } @@ -317,7 +317,7 @@ private void okButton_Click(object sender, EventArgs e) if (selectedIndex > 0) { - AppContext.wcsService.LoadImageLists(); + //AppContext.wcsService.LoadImageLists(); if (LocationManager.isReady) { diff --git a/src/ThemeManager.cs b/src/ThemeManager.cs index 72cdb57..87bd675 100644 --- a/src/ThemeManager.cs +++ b/src/ThemeManager.cs @@ -118,7 +118,7 @@ public static ThemeConfig ImportTheme(string themePath) { Directory.CreateDirectory(Path.Combine("themes", themeName)); - if (Path.GetExtension(themePath) == ".zip") + if (Path.GetExtension(themePath) != ".json") { using (ZipArchive archive = ZipFile.OpenRead(themePath)) { @@ -205,7 +205,9 @@ public static List FindMissingThemes() } List imageIds = new List(); + imageIds.AddRange(theme.sunriseImageList); imageIds.AddRange(theme.dayImageList); + imageIds.AddRange(theme.sunsetImageList); imageIds.AddRange(theme.nightImageList); if (imageFileCount < imageIds.Distinct().Count()) diff --git a/src/WallpaperChangeScheduler.cs b/src/WallpaperChangeScheduler.cs index 52c22e5..f09b23d 100644 --- a/src/WallpaperChangeScheduler.cs +++ b/src/WallpaperChangeScheduler.cs @@ -6,69 +6,112 @@ using System.Globalization; using Microsoft.Win32; using System.IO; -using System.Windows.Forms; +using System.Timers; namespace WinDynamicDesktop { class WallpaperChangeScheduler { - private int[] dayImages; - private int[] nightImages; - private int lastImageId; + private enum DaySegment { Sunrise, Day, Sunset, Night }; - public static bool isDayNow; + private DateTime? nextUpdateTime; - private SolarData yesterdaysData; - private SolarData todaysData; - private SolarData tomorrowsData; + public static bool isNightNow; // TODO Determine how dark mode should work - private Timer wallpaperTimer = new Timer(); - private TimeSpan timerError = new TimeSpan(TimeSpan.TicksPerMillisecond * 55); + private Timer backgroundTimer = new Timer(); + private Timer schedulerTimer = new Timer(); + private const long timerError = (long)(TimeSpan.TicksPerMillisecond * 15.6); public WallpaperChangeScheduler() { - wallpaperTimer.Tick += OnWallpaperTimerTick; + backgroundTimer.AutoReset = true; + backgroundTimer.Interval = 60e3; + backgroundTimer.Elapsed += OnBackgroundTimerElapsed; + backgroundTimer.Start(); + + schedulerTimer.Elapsed += OnSchedulerTimerElapsed; SystemEvents.PowerModeChanged += OnPowerModeChanged; SystemEvents.TimeChanged += OnTimeChanged; + // TODO Change system theme at sunrise/sunset not at these intervals + } - if (ThemeManager.currentTheme != null) + public void RunScheduler() + { + schedulerTimer.Stop(); + + SolarData todaysData = SunriseSunsetService.GetSolarData(DateTime.Today); + DaySegment currentSegment; + + DateTime[] solarTimes = new DateTime[4]; + solarTimes[0] = GetSolarTime(todaysData, DaySegment.Sunrise); + solarTimes[1] = GetSolarTime(todaysData, DaySegment.Day); + solarTimes[2] = GetSolarTime(todaysData, DaySegment.Sunset); + solarTimes[3] = GetSolarTime(todaysData, DaySegment.Night); + + if (solarTimes[0] <= DateTime.Now && DateTime.Now < solarTimes[1]) { - LoadImageLists(); + currentSegment = DaySegment.Sunrise; + } + else if (solarTimes[1] <= DateTime.Now && DateTime.Now < solarTimes[2]) + { + currentSegment = DaySegment.Day; + } + else if (solarTimes[2] <= DateTime.Now && DateTime.Now < solarTimes[3]) + { + currentSegment = DaySegment.Sunset; + } + else + { + currentSegment = DaySegment.Night; } - } - public void LoadImageLists() - { - nightImages = ThemeManager.currentTheme.nightImageList; + isNightNow = (currentSegment == DaySegment.Night); - if (!JsonConfig.settings.darkMode) + if (ThemeManager.currentTheme != null) { - dayImages = ThemeManager.currentTheme.dayImageList; + nextUpdateTime = UpdateImage(solarTimes, currentSegment); + } + else if (!isNightNow) + { + nextUpdateTime = solarTimes[3]; + } + else if (DateTime.Now < solarTimes[0]) + { + nextUpdateTime = solarTimes[0]; } else { - dayImages = nightImages; + SolarData tomorrowsData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(1)); + nextUpdateTime = GetSolarTime(tomorrowsData, DaySegment.Sunrise); } - } - private int GetImageNumber(DateTime startTime, TimeSpan timerLength) - { - TimeSpan elapsedTime = DateTime.Now - startTime; + SystemThemeChanger.TryUpdateSystemTheme(); + JsonConfig.SaveConfig(); - return (int)((elapsedTime.Ticks + timerError.Ticks) / timerLength.Ticks); + StartTimer(nextUpdateTime.Value); } - private void StartTimer(long intervalTicks, TimeSpan maxInterval) + private DateTime GetSolarTime(SolarData data, DaySegment segment) { - if (intervalTicks < timerError.Ticks) + switch (segment) { - intervalTicks += maxInterval.Ticks; + case DaySegment.Sunrise: + return new DateTime(data.SunriseTime.Ticks - TimeSpan.TicksPerHour); + case DaySegment.Day: + return new DateTime(data.SunriseTime.Ticks + TimeSpan.TicksPerHour); + case DaySegment.Sunset: + return new DateTime(data.SunsetTime.Ticks - TimeSpan.TicksPerHour); + default: + return new DateTime(data.SunsetTime.Ticks + TimeSpan.TicksPerHour); } + } - TimeSpan interval = new TimeSpan(intervalTicks); + private int GetImageNumber(DateTime startTime, TimeSpan timerLength) + { + TimeSpan elapsedTime = DateTime.Now - startTime; - wallpaperTimer.Interval = (int)interval.TotalMilliseconds; - wallpaperTimer.Start(); + return (int)(elapsedTime.Ticks / timerLength.Ticks); } private void SetWallpaper(int imageId) @@ -82,117 +125,84 @@ private void SetWallpaper(int imageId) if (UwpDesktop.IsRunningAsUwp() && JsonConfig.settings.changeLockScreen) { - UwpHelper.SetLockScreenImage(imagePath); + UwpHelper.SetLockScreenImage(imageFilename); } - - lastImageId = imageId; } - public void RunScheduler() + private DateTime UpdateImage(DateTime[] solarTimes, DaySegment segment) { - wallpaperTimer.Stop(); - - DateTime today = DateTime.Today; - todaysData = SunriseSunsetService.GetSolarData(today); - - if (DateTime.Now < todaysData.SunriseTime + timerError) - { - // Before sunrise - yesterdaysData = SunriseSunsetService.GetSolarData(today.AddDays(-1)); - tomorrowsData = null; - } - else if (DateTime.Now >= todaysData.SunsetTime - timerError) - { - // After sunset - yesterdaysData = null; - tomorrowsData = SunriseSunsetService.GetSolarData(today.AddDays(1)); - } - else - { - // Between sunrise and sunset - yesterdaysData = null; - tomorrowsData = null; - } - - isDayNow = (yesterdaysData == null && tomorrowsData == null); - lastImageId = -1; - - if (isDayNow) - { - UpdateDayImage(); - } - else - { - UpdateNightImage(); - } - - SystemThemeChanger.TryUpdateSystemTheme(); - JsonConfig.SaveConfig(); + int[] imageList; + DateTime segmentStart; + DateTime segmentEnd; + + switch (segment) + { + case DaySegment.Sunrise: + imageList = ThemeManager.currentTheme.sunriseImageList; + segmentStart = solarTimes[0]; + segmentEnd = solarTimes[1]; + break; + case DaySegment.Day: + imageList = ThemeManager.currentTheme.dayImageList; + segmentStart = solarTimes[1]; + segmentEnd = solarTimes[2]; + TimeSpan dayTime = solarTimes[2] - solarTimes[1]; + break; + case DaySegment.Sunset: + imageList = ThemeManager.currentTheme.sunsetImageList; + segmentStart = solarTimes[2]; + segmentEnd = solarTimes[3]; + break; + default: + imageList = ThemeManager.currentTheme.nightImageList; + + if (DateTime.Now < solarTimes[0]) + { + SolarData yesterdaysData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(-1)); + segmentStart = GetSolarTime(yesterdaysData, DaySegment.Night); + segmentEnd = solarTimes[0]; + } + else + { + segmentStart = solarTimes[3]; + SolarData tomorrowsData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(1)); + segmentEnd = GetSolarTime(tomorrowsData, DaySegment.Sunrise); + } + + break; + } + + TimeSpan segmentLength = segmentEnd - segmentStart; + TimeSpan timerLength = new TimeSpan(segmentLength.Ticks / imageList.Length); + + int imageNumber = GetImageNumber(segmentStart, timerLength); + long nextUpdateTicks = segmentStart.Ticks + timerLength.Ticks * (imageNumber + 1); + + SetWallpaper(imageList[imageNumber]); + + return new DateTime(nextUpdateTicks); } - private void UpdateDayImage() + private void StartTimer(DateTime futureTime) { - TimeSpan dayTime = todaysData.SunsetTime - todaysData.SunriseTime; + long intervalTicks = futureTime.Ticks - DateTime.Now.Ticks; - if (ThemeManager.currentTheme != null) + if (intervalTicks < timerError) { - TimeSpan timerLength = new TimeSpan(dayTime.Ticks / dayImages.Length); - int imageNumber = GetImageNumber(todaysData.SunriseTime, timerLength); - - if (imageNumber >= dayImages.Length) - { - UpdateNightImage(); - return; - } - - StartTimer(todaysData.SunriseTime.Ticks + timerLength.Ticks * (imageNumber + 1) - - DateTime.Now.Ticks, timerLength); - - if (dayImages[imageNumber] != lastImageId) - { - SetWallpaper(dayImages[imageNumber]); - } + intervalTicks = 0; } - else - { - StartTimer(todaysData.SunsetTime.Ticks - DateTime.Now.Ticks, dayTime); - } - } - private void UpdateNightImage() - { - SolarData day1Data = (yesterdaysData == null) ? todaysData : yesterdaysData; - SolarData day2Data = (yesterdaysData == null) ? tomorrowsData : todaysData; - - TimeSpan nightTime = day2Data.SunriseTime - day1Data.SunsetTime; + TimeSpan interval = new TimeSpan(intervalTicks); - if (ThemeManager.currentTheme != null) - { - TimeSpan timerLength = new TimeSpan(nightTime.Ticks / nightImages.Length); - int imageNumber = GetImageNumber(day1Data.SunsetTime, timerLength); - - if (imageNumber >= nightImages.Length) - { - UpdateDayImage(); - return; - } - - StartTimer(day1Data.SunsetTime.Ticks + timerLength.Ticks * (imageNumber + 1) - - DateTime.Now.Ticks, timerLength); - - if (nightImages[imageNumber] != lastImageId) - { - SetWallpaper(nightImages[imageNumber]); - } - } - else - { - StartTimer(day2Data.SunriseTime.Ticks - DateTime.Now.Ticks, nightTime); - } + schedulerTimer.Interval = interval.TotalMilliseconds; + schedulerTimer.Start(); } private void HandleTimerEvent(bool updateLocation) { + // TODO Figure out how to handle no theme correctly if (updateLocation && JsonConfig.settings.useWindowsLocation) { Task.Run(() => UwpLocation.UpdateGeoposition()); @@ -202,14 +212,22 @@ private void HandleTimerEvent(bool updateLocation) UpdateChecker.TryCheckAuto(); } - private void OnWallpaperTimerTick(object sender, EventArgs e) + private void OnBackgroundTimerElapsed(object sender, EventArgs e) + { + if (nextUpdateTime.HasValue && DateTime.Now >= nextUpdateTime.Value) + { + HandleTimerEvent(true); + } + } + + private void OnSchedulerTimerElapsed(object sender, EventArgs e) { HandleTimerEvent(true); } private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e) { - if (e.Mode == PowerModes.Resume && !wallpaperTimer.Enabled) + if (e.Mode == PowerModes.Resume) { HandleTimerEvent(false); } diff --git a/src/WinDynamicDesktop.csproj b/src/WinDynamicDesktop.csproj index 42f2d5b..1819671 100644 --- a/src/WinDynamicDesktop.csproj +++ b/src/WinDynamicDesktop.csproj @@ -53,8 +53,8 @@ packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - packages\RestSharp.106.5.4\lib\net452\RestSharp.dll + + packages\RestSharp.106.6.1\lib\net452\RestSharp.dll diff --git a/src/packages.config b/src/packages.config index d52719f..8ef3f77 100644 --- a/src/packages.config +++ b/src/packages.config @@ -5,6 +5,6 @@ - + \ No newline at end of file diff --git a/src/themes/Mojave_Desert.json b/src/themes/Mojave_Desert.json index 56b6264..384ba0c 100644 --- a/src/themes/Mojave_Desert.json +++ b/src/themes/Mojave_Desert.json @@ -2,15 +2,20 @@ "imagesZipUri": "https://files.rb.gd/mojave_dynamic.zip|https://bitbucket.org/t1m0thyj/wdd-themes/downloads/Mojave_Desert_images.zip", "imageFilename": "mojave_dynamic_*.jpeg", "imageCredits": "Apple", - "dayImageList": [ + "sunriseImageList": [ + 1, 2, - 3, + 3 + ], + "dayImageList": [ 4, 5, 6, 7, 8, - 9, + 9 + ], + "sunsetImageList": [ 10, 11, 12 @@ -19,7 +24,6 @@ 13, 14, 15, - 16, - 1 + 16 ] } diff --git a/src/themes/Solar_Gradients.json b/src/themes/Solar_Gradients.json index 7b9f440..44c7db0 100644 --- a/src/themes/Solar_Gradients.json +++ b/src/themes/Solar_Gradients.json @@ -2,24 +2,28 @@ "imagesZipUri": "https://onedrive.live.com/download?cid=CC2E3BD0360C1775&resid=CC2E3BD0360C1775%21721&authkey=AK4kktXlvN1KJzQ|https://bitbucket.org/t1m0thyj/wdd-themes/downloads/Solar_Gradients_images.zip", "imageFilename": "solar_gradients_*.jpeg", "imageCredits": "Apple", - "dayImageList": [ + "sunriseImageList": [ + 4, 5, - 6, + 6 + ], + "dayImageList": [ 7, 8, 9, 10, - 11, + 11 + ], + "sunsetImageList": [ 12, - 13 + 13, + 14 ], "nightImageList": [ - 14, 15, 16, 1, 2, - 3, - 4 + 3 ] } diff --git a/uwp/Package.appxmanifest b/uwp/Package.appxmanifest index 3c1cbf8..c8d0c49 100644 --- a/uwp/Package.appxmanifest +++ b/uwp/Package.appxmanifest @@ -1,6 +1,6 @@  - + WinDynamicDesktop Timothy Johnson From 2ff65a9436bff31d487e501e4a7a4dbc2acf0ca7 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Tue, 1 Jan 2019 20:29:54 -0500 Subject: [PATCH 2/5] Use SunCalcNet library to calculate 4-segment time periods --- src/InputDialog.Designer.cs | 6 +- src/JsonConfig.cs | 5 +- src/MainMenu.cs | 1 - src/ProgressDialog.cs | 6 +- src/Properties/AssemblyInfo.cs | 2 +- src/SunriseSunset.cs | 43 +++++--- src/SystemThemeChanger.cs | 2 +- src/ThemeDialog.Designer.cs | 38 ++++--- src/ThemeDialog.cs | 146 ++++++++++++++++----------- src/ThemeManager.cs | 66 ++++++------ src/UwpHelper.cs | 2 +- src/WallpaperChangeScheduler.cs | 172 ++++++++++++++++++-------------- src/WinDynamicDesktop.csproj | 17 ++-- src/packages.config | 7 +- 14 files changed, 297 insertions(+), 216 deletions(-) diff --git a/src/InputDialog.Designer.cs b/src/InputDialog.Designer.cs index 22b24b3..9316a39 100644 --- a/src/InputDialog.Designer.cs +++ b/src/InputDialog.Designer.cs @@ -60,7 +60,7 @@ private void InitializeComponent() this.okButton.Margin = new System.Windows.Forms.Padding(4); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(88, 26); - this.okButton.TabIndex = 1; + this.okButton.TabIndex = 2; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); @@ -72,7 +72,7 @@ private void InitializeComponent() this.cancelButton.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(88, 26); - this.cancelButton.TabIndex = 2; + this.cancelButton.TabIndex = 3; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); @@ -83,7 +83,7 @@ private void InitializeComponent() this.locationCheckBox.Location = new System.Drawing.Point(15, 70); this.locationCheckBox.Name = "locationCheckBox"; this.locationCheckBox.Size = new System.Drawing.Size(182, 19); - this.locationCheckBox.TabIndex = 3; + this.locationCheckBox.TabIndex = 1; this.locationCheckBox.Text = "Use Windows location service"; this.locationCheckBox.UseVisualStyleBackColor = true; // diff --git a/src/JsonConfig.cs b/src/JsonConfig.cs index 3ec73d4..73a4a46 100644 --- a/src/JsonConfig.cs +++ b/src/JsonConfig.cs @@ -25,7 +25,8 @@ public class AppConfig public class ThemeConfig { - public string themeName { get; set; } + public string themeId { get; set; } + public string displayName { get; set; } public string imagesZipUri { get; set; } public string imageFilename { get; set; } public string imageCredits { get; set; } @@ -77,7 +78,7 @@ public static ThemeConfig LoadTheme(string name) } ThemeConfig theme = JsonConvert.DeserializeObject(themeJson); - theme.themeName = name; + theme.themeId = name; return theme; } diff --git a/src/MainMenu.cs b/src/MainMenu.cs index 78e53c2..2f3bc65 100644 --- a/src/MainMenu.cs +++ b/src/MainMenu.cs @@ -79,7 +79,6 @@ private static void ToggleDarkMode() JsonConfig.settings.darkMode = isEnabled; darkModeItem.Checked = isEnabled; - //AppContext.wcsService.LoadImageLists(); AppContext.wcsService.RunScheduler(); } diff --git a/src/ProgressDialog.cs b/src/ProgressDialog.cs index 031badd..6c62019 100644 --- a/src/ProgressDialog.cs +++ b/src/ProgressDialog.cs @@ -48,7 +48,7 @@ public void DownloadNext() { List imagesZipUris = theme.imagesZipUri.Split('|').ToList(); client.DownloadFileAsync(new Uri(imagesZipUris.First()), - theme.themeName + "_images.zip", imagesZipUris.Skip(1).ToList()); + theme.themeId + "_images.zip", imagesZipUris.Skip(1).ToList()); } } else @@ -77,7 +77,7 @@ public async void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs { ThemeConfig theme = downloadQueue.Peek(); client.DownloadFileAsync(new Uri(imagesZipUris.First()), - theme.themeName + "_images.zip", imagesZipUris.Skip(1).ToList()); + theme.themeId + "_images.zip", imagesZipUris.Skip(1).ToList()); } else { @@ -86,7 +86,7 @@ public async void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs if (e.Error == null) { await Task.Run(() => ThemeManager.ExtractTheme( - theme.themeName + "_images.zip", theme.themeName, true)); + theme.themeId + "_images.zip", theme.themeId, true)); } DownloadNext(); diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index 7a6c7c9..cc14850 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.3.0")] +[assembly: AssemblyVersion("3.0.0")] //[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/SunriseSunset.cs b/src/SunriseSunset.cs index 975201d..e2a927b 100644 --- a/src/SunriseSunset.cs +++ b/src/SunriseSunset.cs @@ -4,33 +4,52 @@ using System.Text; using System.Threading.Tasks; using System.Globalization; -using Innovative.SolarCalculator; +using SunCalcNet.Model; namespace WinDynamicDesktop { public class SolarData { - public DateTime SunriseTime { get; set; } - public DateTime SunsetTime { get; set; } + public DateTime sunriseTime { get; set; } + public DateTime sunsetTime { get; set; } + public DateTime[] solarTimes { get; set; } } class SunriseSunsetService { - public static SolarData GetSolarData(DateTime date) + private static Dictionary GetSunPhases(DateTime date, string lat, + string lng) { - return GetSolarData(JsonConfig.settings.latitude, JsonConfig.settings.longitude, date); + double latitude = double.Parse(lat, CultureInfo.InvariantCulture); + double longitude = double.Parse(lng, CultureInfo.InvariantCulture); + var sunPhases = new Dictionary(); + + foreach (SunPhase phase in SunCalcNet.SunCalc.GetSunPhases(date, latitude, longitude)) + { + sunPhases.Add(phase.Name.Value, phase.PhaseTime); + } + + return sunPhases; } - public static SolarData GetSolarData(string lat, string lon, DateTime date) + public static SolarData GetSolarData(DateTime date) { - double latitude = double.Parse(lat, CultureInfo.InvariantCulture); - double longitude = double.Parse(lon, CultureInfo.InvariantCulture); + // TODO Why must I add 12 hrs for this to work? + var sunPhases = GetSunPhases(date.AddHours(12).ToUniversalTime(), + JsonConfig.settings.latitude, JsonConfig.settings.longitude); - SolarTimes solarTimes = new SolarTimes(date, latitude, longitude); + SolarData data = new SolarData + { + sunriseTime = sunPhases[SunPhaseName.Sunrise.Value].ToLocalTime(), + sunsetTime = sunPhases[SunPhaseName.Sunset.Value].ToLocalTime(), + solarTimes = new DateTime[4] + }; - SolarData data = new SolarData(); - data.SunriseTime = solarTimes.Sunrise; - data.SunsetTime = solarTimes.Sunset; + data.solarTimes[0] = sunPhases[SunPhaseName.NauticalDawn.Value].ToLocalTime(); + data.solarTimes[1] = sunPhases[SunPhaseName.GoldenHourEnd.Value].ToLocalTime(); + data.solarTimes[2] = sunPhases[SunPhaseName.GoldenHour.Value].ToLocalTime(); + data.solarTimes[3] = sunPhases[SunPhaseName.NauticalDusk.Value].ToLocalTime(); + //System.Windows.Forms.MessageBox.Show(date.ToUniversalTime().ToString() + ",,," + data.solarTimes[0].ToLocalTime().ToString() + "," + data.solarTimes[1].ToLocalTime().ToString() + "," + data.solarTimes[2].ToLocalTime().ToString() + "," + data.solarTimes[3].ToLocalTime().ToString() + ","); return data; } diff --git a/src/SystemThemeChanger.cs b/src/SystemThemeChanger.cs index 259c2e9..944d07d 100644 --- a/src/SystemThemeChanger.cs +++ b/src/SystemThemeChanger.cs @@ -44,7 +44,7 @@ public static void TryUpdateSystemTheme() return; } - bool darkTheme = WallpaperChangeScheduler.isNightNow || JsonConfig.settings.darkMode; + bool darkTheme = !WallpaperChangeScheduler.isSunUp || JsonConfig.settings.darkMode; RegistryKey themeKey = Registry.CurrentUser.OpenSubKey(registryThemeLocation, true); if (darkTheme) diff --git a/src/ThemeDialog.Designer.cs b/src/ThemeDialog.Designer.cs index f51b425..8d256d9 100644 --- a/src/ThemeDialog.Designer.cs +++ b/src/ThemeDialog.Designer.cs @@ -46,6 +46,7 @@ private void InitializeComponent() this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.creditsLabel = new System.Windows.Forms.Label(); + this.applyButton = new System.Windows.Forms.Button(); this.previewBox.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.contextMenuStrip1.SuspendLayout(); @@ -73,7 +74,7 @@ private void InitializeComponent() this.previewBox.Location = new System.Drawing.Point(514, 11); this.previewBox.Name = "previewBox"; this.previewBox.Size = new System.Drawing.Size(404, 275); - this.previewBox.TabIndex = 10; + this.previewBox.TabIndex = 1; this.previewBox.TabStop = false; this.previewBox.Text = "Preview"; // @@ -90,7 +91,7 @@ private void InitializeComponent() this.firstButton.Location = new System.Drawing.Point(15, 240); this.firstButton.Name = "firstButton"; this.firstButton.Size = new System.Drawing.Size(50, 26); - this.firstButton.TabIndex = 8; + this.firstButton.TabIndex = 0; this.firstButton.Text = "<<"; this.firstButton.UseVisualStyleBackColor = true; this.firstButton.Click += new System.EventHandler(this.firstButton_Click); @@ -100,7 +101,7 @@ private void InitializeComponent() this.previousButton.Location = new System.Drawing.Point(80, 240); this.previousButton.Name = "previousButton"; this.previousButton.Size = new System.Drawing.Size(50, 26); - this.previousButton.TabIndex = 9; + this.previousButton.TabIndex = 1; this.previousButton.Text = "<"; this.previousButton.UseVisualStyleBackColor = true; this.previousButton.Click += new System.EventHandler(this.previousButton_Click); @@ -119,7 +120,7 @@ private void InitializeComponent() this.nextButton.Location = new System.Drawing.Point(274, 240); this.nextButton.Name = "nextButton"; this.nextButton.Size = new System.Drawing.Size(50, 26); - this.nextButton.TabIndex = 11; + this.nextButton.TabIndex = 2; this.nextButton.Text = ">"; this.nextButton.UseVisualStyleBackColor = true; this.nextButton.Click += new System.EventHandler(this.nextButton_Click); @@ -129,7 +130,7 @@ private void InitializeComponent() this.lastButton.Location = new System.Drawing.Point(339, 240); this.lastButton.Name = "lastButton"; this.lastButton.Size = new System.Drawing.Size(50, 26); - this.lastButton.TabIndex = 12; + this.lastButton.TabIndex = 3; this.lastButton.Text = ">>"; this.lastButton.UseVisualStyleBackColor = true; this.lastButton.Click += new System.EventHandler(this.lastButton_Click); @@ -140,17 +141,17 @@ private void InitializeComponent() this.darkModeCheckbox.Location = new System.Drawing.Point(381, 330); this.darkModeCheckbox.Name = "darkModeCheckbox"; this.darkModeCheckbox.Size = new System.Drawing.Size(122, 19); - this.darkModeCheckbox.TabIndex = 9; + this.darkModeCheckbox.TabIndex = 4; this.darkModeCheckbox.Text = "Enable Dark Mode"; this.darkModeCheckbox.UseVisualStyleBackColor = true; this.darkModeCheckbox.CheckedChanged += new System.EventHandler(this.darkModeCheckbox_CheckedChanged); // // okButton // - this.okButton.Location = new System.Drawing.Point(610, 325); + this.okButton.Location = new System.Drawing.Point(548, 325); this.okButton.Name = "okButton"; this.okButton.Size = new System.Drawing.Size(88, 26); - this.okButton.TabIndex = 7; + this.okButton.TabIndex = 5; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; this.okButton.Click += new System.EventHandler(this.okButton_Click); @@ -158,10 +159,10 @@ private void InitializeComponent() // cancelButton // this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(733, 325); + this.cancelButton.Location = new System.Drawing.Point(671, 325); this.cancelButton.Name = "cancelButton"; this.cancelButton.Size = new System.Drawing.Size(88, 26); - this.cancelButton.TabIndex = 8; + this.cancelButton.TabIndex = 6; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); @@ -172,7 +173,7 @@ private void InitializeComponent() this.themeLinkLabel.Location = new System.Drawing.Point(159, 330); this.themeLinkLabel.Name = "themeLinkLabel"; this.themeLinkLabel.Size = new System.Drawing.Size(134, 15); - this.themeLinkLabel.TabIndex = 12; + this.themeLinkLabel.TabIndex = 3; this.themeLinkLabel.TabStop = true; this.themeLinkLabel.Text = "Get more themes online"; this.themeLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.themeLinkLabel_LinkClicked); @@ -182,7 +183,7 @@ private void InitializeComponent() this.importButton.Location = new System.Drawing.Point(17, 325); this.importButton.Name = "importButton"; this.importButton.Size = new System.Drawing.Size(125, 26); - this.importButton.TabIndex = 13; + this.importButton.TabIndex = 2; this.importButton.Text = "Import from file..."; this.importButton.UseVisualStyleBackColor = true; this.importButton.Click += new System.EventHandler(this.importButton_Click); @@ -219,6 +220,17 @@ private void InitializeComponent() this.creditsLabel.Text = "label2"; this.creditsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // + // applyButton + // + this.applyButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.applyButton.Location = new System.Drawing.Point(794, 325); + this.applyButton.Name = "applyButton"; + this.applyButton.Size = new System.Drawing.Size(88, 26); + this.applyButton.TabIndex = 7; + this.applyButton.Text = "Apply"; + this.applyButton.UseVisualStyleBackColor = true; + this.applyButton.Click += new System.EventHandler(this.applyButton_Click); + // // ThemeDialog // this.AcceptButton = this.okButton; @@ -226,6 +238,7 @@ private void InitializeComponent() this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.CancelButton = this.cancelButton; this.ClientSize = new System.Drawing.Size(929, 366); + this.Controls.Add(this.applyButton); this.Controls.Add(this.creditsLabel); this.Controls.Add(this.importButton); this.Controls.Add(this.themeLinkLabel); @@ -269,5 +282,6 @@ private void InitializeComponent() private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem; private System.Windows.Forms.Label creditsLabel; + private System.Windows.Forms.Button applyButton; } } \ No newline at end of file diff --git a/src/ThemeDialog.cs b/src/ThemeDialog.cs index 5bbe894..b9fd1c9 100644 --- a/src/ThemeDialog.cs +++ b/src/ThemeDialog.cs @@ -26,7 +26,7 @@ public partial class ThemeDialog : Form public ThemeDialog() { InitializeComponent(); - // TODO Handle 4 segments in image preview, generate thumbnails differently? + this.FormClosing += OnFormClosing; listView1.ContextMenuStrip = contextMenuStrip1; listView1.ListViewItemSorter = new CompareByIndex(listView1); @@ -48,18 +48,25 @@ private Bitmap ShrinkImage(string filename, int width, int height) } } - private Bitmap GetThumbnailImage(ThemeConfig theme, int width, int height) + private Image GetThumbnailImage(ThemeConfig theme, int width, int height) { + string thumbnailPath = Path.Combine("themes", theme.themeId, "thumbnail.png"); + + if (File.Exists(thumbnailPath)) + { + return Image.FromFile(thumbnailPath); + } + int imageId1 = theme.dayImageList[(theme.dayImageList.Length + 1) / 2]; string imageFilename1 = theme.imageFilename.Replace("*", imageId1.ToString()); int imageId2 = theme.nightImageList[(theme.nightImageList.Length + 1) / 2]; string imageFilename2 = theme.imageFilename.Replace("*", imageId2.ToString()); - using (var bmp1 = ShrinkImage(Path.Combine("themes", theme.themeName, imageFilename1), + using (var bmp1 = ShrinkImage(Path.Combine("themes", theme.themeId, imageFilename1), width, height)) { - Bitmap bmp2 = ShrinkImage(Path.Combine("themes", theme.themeName, imageFilename2), + Bitmap bmp2 = ShrinkImage(Path.Combine("themes", theme.themeId, imageFilename2), width, height); using (Graphics g = Graphics.FromImage(bmp2)) @@ -68,17 +75,25 @@ private Bitmap GetThumbnailImage(ThemeConfig theme, int width, int height) GraphicsUnit.Pixel); } + bmp2.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Png); + return bmp2; } } - private string GetCreditsText() + private string GetThemeName(ThemeConfig theme) { - if (selectedIndex == 0) + if (theme.displayName != null) { - return "Image Credits: Microsoft"; + return theme.displayName; } - else + + return theme.themeId.Replace('_', ' '); + } + + private string GetCreditsText() + { + if (selectedIndex > 0) { ThemeConfig theme = ThemeManager.themeSettings[selectedIndex - 1]; @@ -87,6 +102,10 @@ private string GetCreditsText() return "Image Credits: " + theme.imageCredits; } } + else + { + return "Image Credits: Microsoft"; + } return ""; } @@ -102,7 +121,8 @@ private int GetMaxImageNumber() if (!darkModeCheckbox.Checked) { - max += theme.dayImageList.Length; + max += theme.sunriseImageList.Length + theme.dayImageList.Length + + theme.sunsetImageList.Length; } } @@ -123,21 +143,22 @@ private void LoadPreviewImage(int imageNumber) ThemeConfig theme = ThemeManager.themeSettings[selectedIndex - 1]; int imageId; - if (darkModeCheckbox.Checked) - { - imageId = theme.nightImageList[imageNumber - 1]; - } - else if (imageNumber <= theme.dayImageList.Length) + if (!darkModeCheckbox.Checked) { - imageId = theme.dayImageList[imageNumber - 1]; + List imageList = new List(); + imageList.AddRange(theme.sunriseImageList); + imageList.AddRange(theme.dayImageList); + imageList.AddRange(theme.sunsetImageList); + imageList.AddRange(theme.nightImageList); + imageId = imageList[imageNumber - 1]; } else { - imageId = theme.nightImageList[imageNumber - theme.dayImageList.Length - 1]; + imageId = theme.nightImageList[imageNumber - 1]; } string imageFilename = theme.imageFilename.Replace("*", imageId.ToString()); - pictureBox1.Image = ShrinkImage(Path.Combine("themes", theme.themeName, + pictureBox1.Image = ShrinkImage(Path.Combine("themes", theme.themeId, imageFilename), w, h); } @@ -153,7 +174,7 @@ private void LoadPreviewImage(int imageNumber) private async void LoadImportedTheme() { ThemeManager.themeSettings.Add(tempTheme); - ThemeManager.themeSettings.Sort((t1, t2) => t1.themeName.CompareTo(t2.themeName)); + ThemeManager.themeSettings.Sort((t1, t2) => t1.themeId.CompareTo(t2.themeId)); List missingThemes = ThemeManager.FindMissingThemes(); bool isInstalled = missingThemes.IndexOf(tempTheme) == -1; @@ -162,13 +183,13 @@ private async void LoadImportedTheme() { int itemIndex = ThemeManager.themeSettings.IndexOf(tempTheme) + 1; listView1.LargeImageList.Images.Add(GetThumbnailImage(tempTheme, 192, 108)); - listView1.Items.Insert(itemIndex, tempTheme.themeName.Replace('_', ' '), + listView1.Items.Insert(itemIndex, GetThemeName(tempTheme), listView1.LargeImageList.Images.Count - 1); listView1.Items[itemIndex].Selected = true; } else { - MessageBox.Show("Failed to install the '" + tempTheme.themeName.Replace('_', ' ') + + MessageBox.Show("Failed to install the '" + GetThemeName(tempTheme) + "' theme.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); await Task.Run(() => ThemeManager.RemoveTheme(tempTheme)); } @@ -176,10 +197,43 @@ private async void LoadImportedTheme() tempTheme = null; } + private void Apply(bool hideWindow) + { + if (selectedIndex > 0) + { + ThemeManager.currentTheme = ThemeManager.themeSettings[selectedIndex - 1]; + } + else + { + ThemeManager.currentTheme = null; + } + + JsonConfig.settings.themeName = ThemeManager.currentTheme?.themeId; + JsonConfig.settings.darkMode = darkModeCheckbox.Checked; + MainMenu.darkModeItem.Checked = JsonConfig.settings.darkMode; + + if (hideWindow) + { + this.Hide(); + } + + if (selectedIndex > 0) + { + if (LocationManager.isReady) + { + AppContext.wcsService.RunScheduler(); + } + } + else + { + WallpaperApi.SetWallpaper(windowsWallpaper); + } + } + private void ThemeDialog_Load(object sender, EventArgs e) { darkModeCheckbox.Checked = JsonConfig.settings.darkMode; - string currentTheme = ThemeManager.currentTheme?.themeName; + applyButton.Enabled = LocationManager.isReady; ImageList imageList = new ImageList(); imageList.ColorDepth = ColorDepth.Depth32Bit; @@ -189,6 +243,8 @@ private void ThemeDialog_Load(object sender, EventArgs e) imageList.Images.Add(ShrinkImage(windowsWallpaper, 192, 108)); listView1.Items.Add("None", 0); + string currentTheme = ThemeManager.currentTheme?.themeId; + if (currentTheme == null) { if (JsonConfig.firstRun || JsonConfig.settings.themeName != null) @@ -205,9 +261,9 @@ private void ThemeDialog_Load(object sender, EventArgs e) { ThemeConfig theme = ThemeManager.themeSettings[i]; imageList.Images.Add(GetThumbnailImage(theme, 192, 108)); - listView1.Items.Add(theme.themeName.Replace('_', ' '), i + 1); + listView1.Items.Add(GetThemeName(theme), i + 1); - if (theme.themeName == currentTheme) + if (theme.themeId == currentTheme) { listView1.Items[i + 1].Selected = true; } @@ -298,36 +354,7 @@ private void themeLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEvent private void okButton_Click(object sender, EventArgs e) { okButton.Enabled = false; - - string themeName = listView1.SelectedItems[0].Text.Replace(' ', '_'); - JsonConfig.settings.themeName = themeName; - JsonConfig.settings.darkMode = darkModeCheckbox.Checked; - - if (selectedIndex > 0) - { - ThemeManager.currentTheme = ThemeManager.themeSettings[selectedIndex - 1]; - } - else - { - ThemeManager.currentTheme = null; - } - - MainMenu.darkModeItem.Checked = JsonConfig.settings.darkMode; - this.Hide(); - - if (selectedIndex > 0) - { - //AppContext.wcsService.LoadImageLists(); - - if (LocationManager.isReady) - { - AppContext.wcsService.RunScheduler(); - } - } - else - { - WallpaperApi.SetWallpaper(windowsWallpaper); - } + Apply(true); okButton.Enabled = true; this.Close(); @@ -338,13 +365,20 @@ private void cancelButton_Click(object sender, EventArgs e) this.Close(); } + private void applyButton_Click(object sender, EventArgs e) + { + applyButton.Enabled = false; + Apply(false); + applyButton.Enabled = true; + } + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { var hitTestInfo = listView1.HitTest(listView1.PointToClient(Cursor.Position)); int itemIndex = hitTestInfo.Item?.Index ?? -1; if (itemIndex <= 0 || ThemeManager.defaultThemes.Contains( - ThemeManager.themeSettings[itemIndex - 1].themeName)) + ThemeManager.themeSettings[itemIndex - 1].themeId)) { e.Cancel = true; } @@ -356,8 +390,8 @@ private async void removeToolStripMenuItem_Click(object sender, EventArgs e) ThemeConfig theme = ThemeManager.themeSettings[itemIndex - 1]; DialogResult result = MessageBox.Show("Are you sure you want to remove the '" + - theme.themeName.Replace('_', ' ') + "' theme?", "Question", - MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + GetThemeName(theme) + "' theme?", "Question", MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); if (result == DialogResult.Yes) { diff --git a/src/ThemeManager.cs b/src/ThemeManager.cs index 87bd675..8293e3e 100644 --- a/src/ThemeManager.cs +++ b/src/ThemeManager.cs @@ -27,22 +27,22 @@ public static void Initialize() { UpdateThemeFileStructure(); } - - List themeNames = defaultThemes.ToList(); + // TODO Warn people when they have themes with old format + List themeIds = defaultThemes.ToList(); foreach (string filePath in Directory.EnumerateFiles("themes", "*.json", SearchOption.AllDirectories)) { - themeNames.Add(Path.GetFileName(Path.GetDirectoryName(filePath))); + themeIds.Add(Path.GetFileName(Path.GetDirectoryName(filePath))); } - themeNames.Sort(); + themeIds.Sort(); - foreach (string name in themeNames) + foreach (string themeId in themeIds) { - ThemeConfig theme = JsonConfig.LoadTheme(name); + ThemeConfig theme = JsonConfig.LoadTheme(themeId); themeSettings.Add(theme); - if (theme.themeName == JsonConfig.settings.themeName) + if (theme.themeId == JsonConfig.settings.themeName) { currentTheme = theme; } @@ -55,23 +55,23 @@ private static void UpdateThemeFileStructure() { List filePaths = Directory.GetFiles("themes", "*.json").ToList(); filePaths.AddRange(defaultThemes.Select( - themeName => Path.Combine("themes", themeName + ".json"))); + themeId => Path.Combine("themes", themeId + ".json"))); foreach (string filePath in filePaths) { - string themeName = Path.GetFileNameWithoutExtension(filePath); - Directory.CreateDirectory(Path.Combine("themes", themeName)); + string themeId = Path.GetFileNameWithoutExtension(filePath); + Directory.CreateDirectory(Path.Combine("themes", themeId)); if (File.Exists(filePath)) { - File.Move(filePath, Path.Combine("themes", themeName, "theme.json")); + File.Move(filePath, Path.Combine("themes", themeId, "theme.json")); } - ThemeConfig theme = JsonConfig.LoadTheme(themeName); + ThemeConfig theme = JsonConfig.LoadTheme(themeId); foreach (string imagePath in Directory.GetFiles("images", theme.imageFilename)) { File.Move(imagePath, - Path.Combine("themes", themeName, Path.GetFileName(imagePath))); + Path.Combine("themes", themeId, Path.GetFileName(imagePath))); } } @@ -98,14 +98,14 @@ public static void SelectTheme() public static ThemeConfig ImportTheme(string themePath) { - string themeName = Path.GetFileNameWithoutExtension(themePath); + string themeId = Path.GetFileNameWithoutExtension(themePath); bool isInstalled = themeSettings.FindIndex( - theme => theme.themeName == themeName) != -1; + theme => theme.themeId == themeId) != -1; if (isInstalled) { - DialogResult result = MessageBox.Show("The '" + themeName.Replace('_', ' ') + - "' theme is already installed. Do you want to overwrite it?", "Question", + DialogResult result = MessageBox.Show("A theme with the ID '" + themeId + "' is " + + "already installed. Do you want to overwrite it?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result != DialogResult.Yes) @@ -116,7 +116,7 @@ public static ThemeConfig ImportTheme(string themePath) try { - Directory.CreateDirectory(Path.Combine("themes", themeName)); + Directory.CreateDirectory(Path.Combine("themes", themeId)); if (Path.GetExtension(themePath) != ".json") { @@ -124,18 +124,18 @@ public static ThemeConfig ImportTheme(string themePath) { ZipArchiveEntry themeJson = archive.Entries.Single( entry => Path.GetExtension(entry.Name) == ".json"); - themeJson.ExtractToFile(Path.Combine("themes", themeName, "theme.json"), + themeJson.ExtractToFile(Path.Combine("themes", themeId, "theme.json"), true); } - ExtractTheme(themePath, themeName); + ExtractTheme(themePath, themeId); } else { - File.Copy(themePath, Path.Combine("themes", themeName, "theme.json"), true); + File.Copy(themePath, Path.Combine("themes", themeId, "theme.json"), true); } - return JsonConfig.LoadTheme(themeName); + return JsonConfig.LoadTheme(themeId); } catch (Exception e) { @@ -145,11 +145,11 @@ public static ThemeConfig ImportTheme(string themePath) } } - public static void ExtractTheme(string imagesZip, string themeName, bool deleteZip = false) + public static void ExtractTheme(string imagesZip, string themeId, bool deleteZip = false) { try { - string themePath = Path.Combine("themes", themeName); + string themePath = Path.Combine("themes", themeId); Directory.CreateDirectory(themePath); using (ZipArchive archive = ZipFile.OpenRead(imagesZip)) @@ -181,7 +181,7 @@ public static void CopyLocalTheme(ThemeConfig theme, string localPath, try { - File.Copy(imagePath, Path.Combine("themes", theme.themeName, + File.Copy(imagePath, Path.Combine("themes", theme.themeId, Path.GetFileName(imagePath)), true); } catch { } @@ -197,20 +197,20 @@ public static List FindMissingThemes() foreach (ThemeConfig theme in themeSettings) { int imageFileCount = 0; - string themePath = Path.Combine("themes", theme.themeName); + string themePath = Path.Combine("themes", theme.themeId); if (Directory.Exists(themePath)) { imageFileCount = Directory.GetFiles(themePath, theme.imageFilename).Length; } - List imageIds = new List(); - imageIds.AddRange(theme.sunriseImageList); - imageIds.AddRange(theme.dayImageList); - imageIds.AddRange(theme.sunsetImageList); - imageIds.AddRange(theme.nightImageList); + List imageList = new List(); + imageList.AddRange(theme.sunriseImageList); + imageList.AddRange(theme.dayImageList); + imageList.AddRange(theme.sunsetImageList); + imageList.AddRange(theme.nightImageList); - if (imageFileCount < imageIds.Distinct().Count()) + if (imageFileCount < imageList.Distinct().Count()) { missingThemes.Add(theme); } @@ -233,7 +233,7 @@ public static void RemoveTheme(ThemeConfig theme) try { - Directory.Delete(Path.Combine("themes", theme.themeName), true); + Directory.Delete(Path.Combine("themes", theme.themeId), true); } catch { } } diff --git a/src/UwpHelper.cs b/src/UwpHelper.cs index 891fac7..9f5a3c3 100644 --- a/src/UwpHelper.cs +++ b/src/UwpHelper.cs @@ -73,7 +73,7 @@ await Windows.System.Launcher.LaunchUriAsync( public static async void SetLockScreenImage(string imageFilename) { - var uri = new Uri("ms-appdata:///local/themes/" + ThemeManager.currentTheme.themeName + + var uri = new Uri("ms-appdata:///local/themes/" + ThemeManager.currentTheme.themeId + "/" + imageFilename); var file = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri); diff --git a/src/WallpaperChangeScheduler.cs b/src/WallpaperChangeScheduler.cs index f09b23d..26b269c 100644 --- a/src/WallpaperChangeScheduler.cs +++ b/src/WallpaperChangeScheduler.cs @@ -14,9 +14,10 @@ class WallpaperChangeScheduler { private enum DaySegment { Sunrise, Day, Sunset, Night }; + private string lastImagePath; private DateTime? nextUpdateTime; - public static bool isNightNow; // TODO Determine how dark mode should work + public static bool isSunUp; private Timer backgroundTimer = new Timer(); private Timer schedulerTimer = new Timer(); @@ -32,31 +33,24 @@ public WallpaperChangeScheduler() schedulerTimer.Elapsed += OnSchedulerTimerElapsed; SystemEvents.PowerModeChanged += OnPowerModeChanged; SystemEvents.TimeChanged += OnTimeChanged; - // TODO Change system theme at sunrise/sunset not at these intervals } public void RunScheduler() { schedulerTimer.Stop(); - SolarData todaysData = SunriseSunsetService.GetSolarData(DateTime.Today); + SolarData data = SunriseSunsetService.GetSolarData(DateTime.Today); DaySegment currentSegment; - DateTime[] solarTimes = new DateTime[4]; - solarTimes[0] = GetSolarTime(todaysData, DaySegment.Sunrise); - solarTimes[1] = GetSolarTime(todaysData, DaySegment.Day); - solarTimes[2] = GetSolarTime(todaysData, DaySegment.Sunset); - solarTimes[3] = GetSolarTime(todaysData, DaySegment.Night); - - if (solarTimes[0] <= DateTime.Now && DateTime.Now < solarTimes[1]) + if (data.solarTimes[0] <= DateTime.Now && DateTime.Now < data.solarTimes[1]) { currentSegment = DaySegment.Sunrise; } - else if (solarTimes[1] <= DateTime.Now && DateTime.Now < solarTimes[2]) + else if (data.solarTimes[1] <= DateTime.Now && DateTime.Now < data.solarTimes[2]) { currentSegment = DaySegment.Day; } - else if (solarTimes[2] <= DateTime.Now && DateTime.Now < solarTimes[3]) + else if (data.solarTimes[2] <= DateTime.Now && DateTime.Now < data.solarTimes[3]) { currentSegment = DaySegment.Sunset; } @@ -65,46 +59,38 @@ public void RunScheduler() currentSegment = DaySegment.Night; } - isNightNow = (currentSegment == DaySegment.Night); + isSunUp = (data.sunriseTime <= DateTime.Now && DateTime.Now < data.sunsetTime); + DateTime? nextImageUpdateTime = null; if (ThemeManager.currentTheme != null) { - nextUpdateTime = UpdateImage(solarTimes, currentSegment); + nextImageUpdateTime = UpdateImage(data, currentSegment); } - else if (!isNightNow) + + SystemThemeChanger.TryUpdateSystemTheme(); + + if (isSunUp) { - nextUpdateTime = solarTimes[3]; + nextUpdateTime = data.sunsetTime; } - else if (DateTime.Now < solarTimes[0]) + else if (DateTime.Now < data.solarTimes[0]) { - nextUpdateTime = solarTimes[0]; + nextUpdateTime = data.sunriseTime; } else { SolarData tomorrowsData = SunriseSunsetService.GetSolarData( DateTime.Today.AddDays(1)); - nextUpdateTime = GetSolarTime(tomorrowsData, DaySegment.Sunrise); + nextUpdateTime = tomorrowsData.sunriseTime; } - SystemThemeChanger.TryUpdateSystemTheme(); - JsonConfig.SaveConfig(); - - StartTimer(nextUpdateTime.Value); - } - - private DateTime GetSolarTime(SolarData data, DaySegment segment) - { - switch (segment) + if (nextImageUpdateTime.HasValue && nextImageUpdateTime.Value < nextUpdateTime.Value) { - case DaySegment.Sunrise: - return new DateTime(data.SunriseTime.Ticks - TimeSpan.TicksPerHour); - case DaySegment.Day: - return new DateTime(data.SunriseTime.Ticks + TimeSpan.TicksPerHour); - case DaySegment.Sunset: - return new DateTime(data.SunsetTime.Ticks - TimeSpan.TicksPerHour); - default: - return new DateTime(data.SunsetTime.Ticks + TimeSpan.TicksPerHour); + nextUpdateTime = nextImageUpdateTime; } + + StartTimer(nextUpdateTime.Value); + JsonConfig.SaveConfig(); } private int GetImageNumber(DateTime startTime, TimeSpan timerLength) @@ -119,7 +105,12 @@ private void SetWallpaper(int imageId) string imageFilename = ThemeManager.currentTheme.imageFilename.Replace("*", imageId.ToString()); string imagePath = Path.Combine(Directory.GetCurrentDirectory(), "themes", - ThemeManager.currentTheme.themeName, imageFilename); + ThemeManager.currentTheme.themeId, imageFilename); + + if (imagePath == lastImagePath) + { + return; + } WallpaperApi.SetWallpaper(imagePath); @@ -127,51 +118,79 @@ private void SetWallpaper(int imageId) { UwpHelper.SetLockScreenImage(imageFilename); } + + lastImagePath = imagePath; } - private DateTime UpdateImage(DateTime[] solarTimes, DaySegment segment) + private DateTime UpdateImage(SolarData data, DaySegment segment) { int[] imageList; DateTime segmentStart; DateTime segmentEnd; - switch (segment) - { - case DaySegment.Sunrise: - imageList = ThemeManager.currentTheme.sunriseImageList; - segmentStart = solarTimes[0]; - segmentEnd = solarTimes[1]; - break; - case DaySegment.Day: - imageList = ThemeManager.currentTheme.dayImageList; - segmentStart = solarTimes[1]; - segmentEnd = solarTimes[2]; - TimeSpan dayTime = solarTimes[2] - solarTimes[1]; - break; - case DaySegment.Sunset: - imageList = ThemeManager.currentTheme.sunsetImageList; - segmentStart = solarTimes[2]; - segmentEnd = solarTimes[3]; - break; - default: - imageList = ThemeManager.currentTheme.nightImageList; - - if (DateTime.Now < solarTimes[0]) - { - SolarData yesterdaysData = SunriseSunsetService.GetSolarData( - DateTime.Today.AddDays(-1)); - segmentStart = GetSolarTime(yesterdaysData, DaySegment.Night); - segmentEnd = solarTimes[0]; - } - else - { - segmentStart = solarTimes[3]; - SolarData tomorrowsData = SunriseSunsetService.GetSolarData( - DateTime.Today.AddDays(1)); - segmentEnd = GetSolarTime(tomorrowsData, DaySegment.Sunrise); - } - - break; + if (!JsonConfig.settings.darkMode) + { + switch (segment) + { + case DaySegment.Sunrise: + imageList = ThemeManager.currentTheme.sunriseImageList; + segmentStart = data.solarTimes[0]; + segmentEnd = data.solarTimes[1]; + break; + case DaySegment.Day: + imageList = ThemeManager.currentTheme.dayImageList; + segmentStart = data.solarTimes[1]; + segmentEnd = data.solarTimes[2]; + break; + case DaySegment.Sunset: + imageList = ThemeManager.currentTheme.sunsetImageList; + segmentStart = data.solarTimes[2]; + segmentEnd = data.solarTimes[3]; + break; + default: + imageList = ThemeManager.currentTheme.nightImageList; + + if (DateTime.Now < data.solarTimes[0]) + { + SolarData yesterdaysData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(-1)); + segmentStart = yesterdaysData.solarTimes[3]; + segmentEnd = data.solarTimes[0]; + } + else + { + segmentStart = data.solarTimes[3]; + SolarData tomorrowsData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(1)); + segmentEnd = tomorrowsData.solarTimes[0]; + } + + break; + } + } + else + { + imageList = ThemeManager.currentTheme.nightImageList; + + if (isSunUp) + { + segmentStart = data.sunriseTime; + segmentEnd = data.sunsetTime; + } + else if (DateTime.Now < data.sunriseTime) + { + SolarData yesterdaysData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(-1)); + segmentStart = yesterdaysData.sunsetTime; + segmentEnd = data.sunriseTime; + } + else + { + segmentStart = data.sunsetTime; + SolarData tomorrowsData = SunriseSunsetService.GetSolarData( + DateTime.Today.AddDays(1)); + segmentEnd = tomorrowsData.sunriseTime; + } } TimeSpan segmentLength = segmentEnd - segmentStart; @@ -191,7 +210,7 @@ private void StartTimer(DateTime futureTime) if (intervalTicks < timerError) { - intervalTicks = 0; + intervalTicks = 1; } TimeSpan interval = new TimeSpan(intervalTicks); @@ -202,7 +221,6 @@ private void StartTimer(DateTime futureTime) private void HandleTimerEvent(bool updateLocation) { - // TODO Figure out how to handle no theme correctly if (updateLocation && JsonConfig.settings.useWindowsLocation) { Task.Run(() => UwpLocation.UpdateGeoposition()); diff --git a/src/WinDynamicDesktop.csproj b/src/WinDynamicDesktop.csproj index 1819671..19b9174 100644 --- a/src/WinDynamicDesktop.csproj +++ b/src/WinDynamicDesktop.csproj @@ -44,17 +44,14 @@ packages\DesktopBridge.Helpers.1.1\lib\net45\DesktopBridge.Helpers.dll - - packages\Angle.2.0.0\lib\netstandard1.2\Innovative.Geometry.Angle.dll - - - packages\SolarCalculator.2.0.4\lib\netstandard1.2\Innovative.SolarCalculator.dll - packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - packages\RestSharp.106.6.1\lib\net452\RestSharp.dll + + packages\RestSharp.106.6.2\lib\net452\RestSharp.dll + + + packages\SunCalcNet.1.0.2\lib\net461\SunCalcNet.dll @@ -169,7 +166,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + - + \ No newline at end of file diff --git a/src/packages.config b/src/packages.config index 8ef3f77..1c3c10a 100644 --- a/src/packages.config +++ b/src/packages.config @@ -1,10 +1,9 @@  - - + - - + + \ No newline at end of file From eb390fee21a010316fd9b9b5a7f2af7882f7c511 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Thu, 3 Jan 2019 20:11:24 -0500 Subject: [PATCH 3/5] Fixed path logic and improved UX for importing themes --- src/DesktopHelper.cs | 6 ++---- src/MainMenu.cs | 2 +- src/Program.cs | 4 ++-- src/ThemeDialog.cs | 3 +++ src/ThemeManager.cs | 11 ++++++++--- src/WallpaperChangeScheduler.cs | 8 ++++++-- src/WinDynamicDesktop.csproj | 18 +++++++++--------- src/packages.config | 4 ++-- 8 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/DesktopHelper.cs b/src/DesktopHelper.cs index 25341b6..3caa2c7 100644 --- a/src/DesktopHelper.cs +++ b/src/DesktopHelper.cs @@ -19,7 +19,7 @@ class DesktopHelper : PlatformHelper public override string GetCurrentDirectory() { - return Path.GetDirectoryName(Application.ExecutablePath); + return Application.StartupPath; } public override void CheckStartOnBoot() @@ -37,9 +37,7 @@ public override void ToggleStartOnBoot() if (!startOnBoot) { - string exePath = Path.Combine(Directory.GetCurrentDirectory(), - Environment.GetCommandLineArgs()[0]); - startupKey.SetValue("WinDynamicDesktop", exePath); + startupKey.SetValue("WinDynamicDesktop", Application.ExecutablePath); startOnBoot = true; } else diff --git a/src/MainMenu.cs b/src/MainMenu.cs index 2f3bc65..e396b7f 100644 --- a/src/MainMenu.cs +++ b/src/MainMenu.cs @@ -94,7 +94,7 @@ private static void OnLocationItemClick(object sender, EventArgs e) private static void OnRefreshItemClick(object sender, EventArgs e) { - AppContext.wcsService.RunScheduler(); + AppContext.wcsService.RunScheduler(true); } private static void OnDarkModeClick(object sender, EventArgs e) diff --git a/src/Program.cs b/src/Program.cs index 81dae12..fa8ce7d 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -16,7 +16,7 @@ static class Program [STAThread] static void Main() { - Environment.CurrentDirectory = UwpDesktop.GetHelper().GetCurrentDirectory(); + Directory.SetCurrentDirectory(UwpDesktop.GetHelper().GetCurrentDirectory()); Application.ThreadException += OnThreadException; AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; @@ -39,7 +39,7 @@ static void LogError(Exception exc) { string errorMessage = exc.ToString() + "\n"; string logFilename = Path.Combine(Directory.GetCurrentDirectory(), - Environment.GetCommandLineArgs()[0] + ".log"); + Path.GetFileName(Environment.GetCommandLineArgs()[0]) + ".log"); try { diff --git a/src/ThemeDialog.cs b/src/ThemeDialog.cs index b9fd1c9..c7a728c 100644 --- a/src/ThemeDialog.cs +++ b/src/ThemeDialog.cs @@ -186,6 +186,7 @@ private async void LoadImportedTheme() listView1.Items.Insert(itemIndex, GetThemeName(tempTheme), listView1.LargeImageList.Images.Count - 1); listView1.Items[itemIndex].Selected = true; + listView1.EnsureVisible(itemIndex); } else { @@ -324,6 +325,8 @@ private void importButton_Click(object sender, EventArgs e) } string themePath = openFileDialog1.FileName; + openFileDialog1.InitialDirectory = Path.GetDirectoryName(themePath); + openFileDialog1.FileName = ""; tempTheme = ThemeManager.ImportTheme(themePath); if (tempTheme == null) diff --git a/src/ThemeManager.cs b/src/ThemeManager.cs index 8293e3e..4f43187 100644 --- a/src/ThemeManager.cs +++ b/src/ThemeManager.cs @@ -288,10 +288,15 @@ private static void OnDownloadDialogClosed(object sender, EventArgs e) else { DialogResult result = MessageBox.Show("Failed to download images. Click Retry " + - "to try again or Cancel to continue with some themes disabled.", "Error", - MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning); + "to try again, Ignore to continue with some themes disabled, or Abort to " + + "exit the program.", "Error", MessageBoxButtons.AbortRetryIgnore, + MessageBoxIcon.Warning); - if (result == DialogResult.Retry) + if (result == DialogResult.Abort) + { + Environment.Exit(0); + } + else if (result == DialogResult.Retry) { DownloadMissingImages(missingThemes); } diff --git a/src/WallpaperChangeScheduler.cs b/src/WallpaperChangeScheduler.cs index 26b269c..d843a7e 100644 --- a/src/WallpaperChangeScheduler.cs +++ b/src/WallpaperChangeScheduler.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Globalization; using Microsoft.Win32; using System.IO; using System.Timers; @@ -35,7 +34,7 @@ public WallpaperChangeScheduler() SystemEvents.TimeChanged += OnTimeChanged; } - public void RunScheduler() + public void RunScheduler(bool forceImageUpdate = false) { schedulerTimer.Stop(); @@ -64,6 +63,11 @@ public void RunScheduler() if (ThemeManager.currentTheme != null) { + if (forceImageUpdate) + { + lastImagePath = null; + } + nextImageUpdateTime = UpdateImage(data, currentSegment); } diff --git a/src/WinDynamicDesktop.csproj b/src/WinDynamicDesktop.csproj index 19b9174..678f9f3 100644 --- a/src/WinDynamicDesktop.csproj +++ b/src/WinDynamicDesktop.csproj @@ -1,6 +1,6 @@  - + Debug @@ -38,8 +38,8 @@ WinDynamicDesktop.ico - - packages\Costura.Fody.3.2.1\lib\net40\Costura.dll + + packages\Costura.Fody.3.2.2\lib\net40\Costura.dll packages\DesktopBridge.Helpers.1.1\lib\net45\DesktopBridge.Helpers.dll @@ -47,21 +47,20 @@ packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - packages\RestSharp.106.6.2\lib\net452\RestSharp.dll + + packages\RestSharp.106.6.3\lib\net452\RestSharp.dll packages\SunCalcNet.1.0.2\lib\net461\SunCalcNet.dll - - False C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\System.Runtime.WindowsRuntime.dll + False @@ -73,7 +72,8 @@ - C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17134.0\Windows.winmd + C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17763.0\Windows.winmd + False @@ -165,8 +165,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/src/packages.config b/src/packages.config index 1c3c10a..eea2f93 100644 --- a/src/packages.config +++ b/src/packages.config @@ -1,9 +1,9 @@  - + - + \ No newline at end of file From 538a5888662d2311ee458d40903a46463e443c1d Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Mon, 7 Jan 2019 06:59:23 -0500 Subject: [PATCH 4/5] Disable themes on startup that fail to load instead of crashing --- src/InputDialog.Designer.cs | 2 +- src/InputDialog.cs | 5 --- src/LocationManager.cs | 4 +- src/MainMenu.cs | 4 +- src/SunriseSunset.cs | 4 +- src/ThemeDialog.Designer.cs | 64 +++++++++++----------------- src/ThemeDialog.cs | 84 ++++++++++++++----------------------- src/ThemeManager.cs | 42 +++++++++++++++---- 8 files changed, 96 insertions(+), 113 deletions(-) diff --git a/src/InputDialog.Designer.cs b/src/InputDialog.Designer.cs index 9316a39..ba435c1 100644 --- a/src/InputDialog.Designer.cs +++ b/src/InputDialog.Designer.cs @@ -107,7 +107,7 @@ private void InitializeComponent() this.MinimizeBox = false; this.Name = "InputDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Set Location"; + this.Text = "Change Location"; this.Load += new System.EventHandler(this.InputDialog_Load); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/InputDialog.cs b/src/InputDialog.cs index 2d6e235..43c251d 100644 --- a/src/InputDialog.cs +++ b/src/InputDialog.cs @@ -84,8 +84,6 @@ private async void okButton_Click(object sender, EventArgs e) JsonConfig.settings.latitude = data.lat; JsonConfig.settings.longitude = data.lon; - this.Hide(); - if (ThemeManager.isReady) { AppContext.wcsService.RunScheduler(); @@ -106,7 +104,6 @@ private async void okButton_Click(object sender, EventArgs e) } else { - this.Hide(); bool locationUpdated = await UwpLocation.UpdateGeoposition(); if (locationUpdated) @@ -122,8 +119,6 @@ private async void okButton_Click(object sender, EventArgs e) { MessageBox.Show("Failed to get location from Windows location service.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); - - this.Show(); } } diff --git a/src/LocationManager.cs b/src/LocationManager.cs index ed0624c..f2b828e 100644 --- a/src/LocationManager.cs +++ b/src/LocationManager.cs @@ -31,11 +31,11 @@ public static void Initialize() } else { - UpdateLocation(); + ChangeLocation(); } } - public static void UpdateLocation() + public static void ChangeLocation() { if (locationDialog == null) { diff --git a/src/MainMenu.cs b/src/MainMenu.cs index e396b7f..b9c155d 100644 --- a/src/MainMenu.cs +++ b/src/MainMenu.cs @@ -35,7 +35,7 @@ private static List GetMenuItems() new ToolStripMenuItem("WinDynamicDesktop"), new ToolStripSeparator(), themeItem, - new ToolStripMenuItem("&Update Location...", null, OnLocationItemClick) + new ToolStripMenuItem("&Change Location...", null, OnLocationItemClick) }); items[0].Enabled = false; @@ -89,7 +89,7 @@ private static void OnThemeItemClick(object sender, EventArgs e) private static void OnLocationItemClick(object sender, EventArgs e) { - LocationManager.UpdateLocation(); + LocationManager.ChangeLocation(); } private static void OnRefreshItemClick(object sender, EventArgs e) diff --git a/src/SunriseSunset.cs b/src/SunriseSunset.cs index e2a927b..b6bc988 100644 --- a/src/SunriseSunset.cs +++ b/src/SunriseSunset.cs @@ -34,7 +34,6 @@ private static Dictionary GetSunPhases(DateTime date, string la public static SolarData GetSolarData(DateTime date) { - // TODO Why must I add 12 hrs for this to work? var sunPhases = GetSunPhases(date.AddHours(12).ToUniversalTime(), JsonConfig.settings.latitude, JsonConfig.settings.longitude); @@ -49,8 +48,7 @@ public static SolarData GetSolarData(DateTime date) data.solarTimes[1] = sunPhases[SunPhaseName.GoldenHourEnd.Value].ToLocalTime(); data.solarTimes[2] = sunPhases[SunPhaseName.GoldenHour.Value].ToLocalTime(); data.solarTimes[3] = sunPhases[SunPhaseName.NauticalDusk.Value].ToLocalTime(); - //System.Windows.Forms.MessageBox.Show(date.ToUniversalTime().ToString() + ",,," + data.solarTimes[0].ToLocalTime().ToString() + "," + data.solarTimes[1].ToLocalTime().ToString() + "," + data.solarTimes[2].ToLocalTime().ToString() + "," + data.solarTimes[3].ToLocalTime().ToString() + ","); - + return data; } } diff --git a/src/ThemeDialog.Designer.cs b/src/ThemeDialog.Designer.cs index 8d256d9..b3dae60 100644 --- a/src/ThemeDialog.Designer.cs +++ b/src/ThemeDialog.Designer.cs @@ -38,15 +38,14 @@ private void InitializeComponent() this.nextButton = new System.Windows.Forms.Button(); this.lastButton = new System.Windows.Forms.Button(); this.darkModeCheckbox = new System.Windows.Forms.CheckBox(); - this.okButton = new System.Windows.Forms.Button(); - this.cancelButton = new System.Windows.Forms.Button(); + this.applyButton = new System.Windows.Forms.Button(); + this.closeButton = new System.Windows.Forms.Button(); this.themeLinkLabel = new System.Windows.Forms.LinkLabel(); this.importButton = new System.Windows.Forms.Button(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.creditsLabel = new System.Windows.Forms.Label(); - this.applyButton = new System.Windows.Forms.Button(); this.previewBox.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.contextMenuStrip1.SuspendLayout(); @@ -146,26 +145,26 @@ private void InitializeComponent() this.darkModeCheckbox.UseVisualStyleBackColor = true; this.darkModeCheckbox.CheckedChanged += new System.EventHandler(this.darkModeCheckbox_CheckedChanged); // - // okButton + // applyButton // - this.okButton.Location = new System.Drawing.Point(548, 325); - this.okButton.Name = "okButton"; - this.okButton.Size = new System.Drawing.Size(88, 26); - this.okButton.TabIndex = 5; - this.okButton.Text = "OK"; - this.okButton.UseVisualStyleBackColor = true; - this.okButton.Click += new System.EventHandler(this.okButton_Click); + this.applyButton.Location = new System.Drawing.Point(610, 325); + this.applyButton.Name = "applyButton"; + this.applyButton.Size = new System.Drawing.Size(88, 26); + this.applyButton.TabIndex = 5; + this.applyButton.Text = "Apply"; + this.applyButton.UseVisualStyleBackColor = true; + this.applyButton.Click += new System.EventHandler(this.applyButton_Click); // - // cancelButton + // closeButton // - this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.cancelButton.Location = new System.Drawing.Point(671, 325); - this.cancelButton.Name = "cancelButton"; - this.cancelButton.Size = new System.Drawing.Size(88, 26); - this.cancelButton.TabIndex = 6; - this.cancelButton.Text = "Cancel"; - this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); + this.closeButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.closeButton.Location = new System.Drawing.Point(733, 325); + this.closeButton.Name = "closeButton"; + this.closeButton.Size = new System.Drawing.Size(88, 26); + this.closeButton.TabIndex = 6; + this.closeButton.Text = "Close"; + this.closeButton.UseVisualStyleBackColor = true; + this.closeButton.Click += new System.EventHandler(this.closeButton_Click); // // themeLinkLabel // @@ -220,33 +219,21 @@ private void InitializeComponent() this.creditsLabel.Text = "label2"; this.creditsLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // - // applyButton - // - this.applyButton.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.applyButton.Location = new System.Drawing.Point(794, 325); - this.applyButton.Name = "applyButton"; - this.applyButton.Size = new System.Drawing.Size(88, 26); - this.applyButton.TabIndex = 7; - this.applyButton.Text = "Apply"; - this.applyButton.UseVisualStyleBackColor = true; - this.applyButton.Click += new System.EventHandler(this.applyButton_Click); - // // ThemeDialog // - this.AcceptButton = this.okButton; + this.AcceptButton = this.applyButton; this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.CancelButton = this.cancelButton; + this.CancelButton = this.closeButton; this.ClientSize = new System.Drawing.Size(929, 366); - this.Controls.Add(this.applyButton); this.Controls.Add(this.creditsLabel); this.Controls.Add(this.importButton); this.Controls.Add(this.themeLinkLabel); this.Controls.Add(this.listView1); this.Controls.Add(this.previewBox); this.Controls.Add(this.darkModeCheckbox); - this.Controls.Add(this.okButton); - this.Controls.Add(this.cancelButton); + this.Controls.Add(this.applyButton); + this.Controls.Add(this.closeButton); this.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = global::WinDynamicDesktop.Properties.Resources.AppIcon; @@ -274,14 +261,13 @@ private void InitializeComponent() private System.Windows.Forms.Button nextButton; private System.Windows.Forms.Button lastButton; private System.Windows.Forms.CheckBox darkModeCheckbox; - private System.Windows.Forms.Button okButton; - private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.Button applyButton; + private System.Windows.Forms.Button closeButton; private System.Windows.Forms.LinkLabel themeLinkLabel; private System.Windows.Forms.Button importButton; private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem; private System.Windows.Forms.Label creditsLabel; - private System.Windows.Forms.Button applyButton; } } \ No newline at end of file diff --git a/src/ThemeDialog.cs b/src/ThemeDialog.cs index c7a728c..9fbfb40 100644 --- a/src/ThemeDialog.cs +++ b/src/ThemeDialog.cs @@ -190,47 +190,14 @@ private async void LoadImportedTheme() } else { - MessageBox.Show("Failed to install the '" + GetThemeName(tempTheme) + - "' theme.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); + MessageBox.Show("Failed to install the " + GetThemeName(tempTheme) + + " theme.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); await Task.Run(() => ThemeManager.RemoveTheme(tempTheme)); } tempTheme = null; } - private void Apply(bool hideWindow) - { - if (selectedIndex > 0) - { - ThemeManager.currentTheme = ThemeManager.themeSettings[selectedIndex - 1]; - } - else - { - ThemeManager.currentTheme = null; - } - - JsonConfig.settings.themeName = ThemeManager.currentTheme?.themeId; - JsonConfig.settings.darkMode = darkModeCheckbox.Checked; - MainMenu.darkModeItem.Checked = JsonConfig.settings.darkMode; - - if (hideWindow) - { - this.Hide(); - } - - if (selectedIndex > 0) - { - if (LocationManager.isReady) - { - AppContext.wcsService.RunScheduler(); - } - } - else - { - WallpaperApi.SetWallpaper(windowsWallpaper); - } - } - private void ThemeDialog_Load(object sender, EventArgs e) { darkModeCheckbox.Checked = JsonConfig.settings.darkMode; @@ -281,11 +248,11 @@ private void listView1_SelectedIndexChanged(object sender, EventArgs e) maxImageNumber = GetMaxImageNumber(); LoadPreviewImage(1); - okButton.Enabled = true; + applyButton.Enabled = true; } else { - okButton.Enabled = false; + applyButton.Enabled = false; } } @@ -354,25 +321,38 @@ private void themeLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEvent System.Diagnostics.Process.Start(themeLink); } - private void okButton_Click(object sender, EventArgs e) + private void applyButton_Click(object sender, EventArgs e) { - okButton.Enabled = false; - Apply(true); + applyButton.Enabled = false; - okButton.Enabled = true; - this.Close(); - } + if (selectedIndex > 0) + { + ThemeManager.currentTheme = ThemeManager.themeSettings[selectedIndex - 1]; + } + else + { + ThemeManager.currentTheme = null; + } - private void cancelButton_Click(object sender, EventArgs e) - { - this.Close(); + JsonConfig.settings.themeName = ThemeManager.currentTheme?.themeId; + JsonConfig.settings.darkMode = darkModeCheckbox.Checked; + MainMenu.darkModeItem.Checked = JsonConfig.settings.darkMode; + + if (selectedIndex == 0) + { + WallpaperApi.SetWallpaper(windowsWallpaper); + } + else if (LocationManager.isReady) + { + AppContext.wcsService.RunScheduler(); + } + + applyButton.Enabled = true; } - private void applyButton_Click(object sender, EventArgs e) + private void closeButton_Click(object sender, EventArgs e) { - applyButton.Enabled = false; - Apply(false); - applyButton.Enabled = true; + this.Close(); } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) @@ -392,8 +372,8 @@ private async void removeToolStripMenuItem_Click(object sender, EventArgs e) int itemIndex = listView1.FocusedItem.Index; ThemeConfig theme = ThemeManager.themeSettings[itemIndex - 1]; - DialogResult result = MessageBox.Show("Are you sure you want to remove the '" + - GetThemeName(theme) + "' theme?", "Question", MessageBoxButtons.YesNo, + DialogResult result = MessageBox.Show("Are you sure you want to remove the " + + GetThemeName(theme) + " theme?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.Yes) diff --git a/src/ThemeManager.cs b/src/ThemeManager.cs index 4f43187..aa520ba 100644 --- a/src/ThemeManager.cs +++ b/src/ThemeManager.cs @@ -27,24 +27,38 @@ public static void Initialize() { UpdateThemeFileStructure(); } - // TODO Warn people when they have themes with old format + List themeIds = defaultThemes.ToList(); foreach (string filePath in Directory.EnumerateFiles("themes", "*.json", SearchOption.AllDirectories)) { - themeIds.Add(Path.GetFileName(Path.GetDirectoryName(filePath))); + string themeId = Path.GetFileName(Path.GetDirectoryName(filePath)); + + if (!themeId.StartsWith(".")) + { + themeIds.Add(themeId); + } } + themeIds.Sort(); foreach (string themeId in themeIds) { - ThemeConfig theme = JsonConfig.LoadTheme(themeId); - themeSettings.Add(theme); + try + { + ThemeConfig theme = JsonConfig.LoadTheme(themeId); + + themeSettings.Add(theme); - if (theme.themeId == JsonConfig.settings.themeName) + if (theme.themeId == JsonConfig.settings.themeName) + { + currentTheme = theme; + } + } + catch { - currentTheme = theme; + DisableTheme(themeId); } } @@ -104,9 +118,9 @@ public static ThemeConfig ImportTheme(string themePath) if (isInstalled) { - DialogResult result = MessageBox.Show("A theme with the ID '" + themeId + "' is " + - "already installed. Do you want to overwrite it?", "Question", - MessageBoxButtons.YesNo, MessageBoxIcon.Warning); + DialogResult result = MessageBox.Show("The '" + themeId + "' theme is already " + + "installed. Do you want to overwrite it?", "Question", MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); if (result != DialogResult.Yes) { @@ -238,6 +252,16 @@ public static void RemoveTheme(ThemeConfig theme) catch { } } + private static void DisableTheme(string themeId) + { + Directory.Move(Path.Combine("themes", themeId), Path.Combine("themes", "." + themeId)); + + MessageBox.Show("The '" + themeId + "' theme could not be loaded and has been " + + "disabled. This is probably because it was developed for an older version of " + + "the app or its config file is formatted incorrectly.", "Error", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + private static void ReadyUp() { if (currentTheme == null && (JsonConfig.firstRun From c85cdfc40b48fb524f45ada171b49baa165eea7f Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Tue, 8 Jan 2019 22:57:15 -0500 Subject: [PATCH 5/5] Upgrade old 2-segment themes for compatibility --- src/Compatibility.cs | 128 +++++++++++++++++++++++++++++++++++ src/ThemeDialog.cs | 4 +- src/ThemeManager.cs | 64 ++++-------------- src/WinDynamicDesktop.csproj | 13 ++-- src/packages.config | 4 +- 5 files changed, 153 insertions(+), 60 deletions(-) create mode 100644 src/Compatibility.cs diff --git a/src/Compatibility.cs b/src/Compatibility.cs new file mode 100644 index 0000000..2ee43ec --- /dev/null +++ b/src/Compatibility.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using Newtonsoft.Json; + +namespace WinDynamicDesktop +{ + class Compatibility + { + public static void CompatibilizeThemes() + { + if (Directory.Exists("images")) + { + UpdateThemeFileStructure(); + } + + UpdateThemeImageLists(); + } + + // TODO Remove after 2.3.0 + private static void UpdateThemeFileStructure() + { + List filePaths = Directory.GetFiles("themes", "*.json").ToList(); + filePaths.AddRange(ThemeManager.defaultThemes.Select( + themeId => Path.Combine("themes", themeId + ".json"))); + + foreach (string filePath in filePaths) + { + string themeId = Path.GetFileNameWithoutExtension(filePath); + Directory.CreateDirectory(Path.Combine("themes", themeId)); + + if (File.Exists(filePath)) + { + File.Move(filePath, Path.Combine("themes", themeId, "theme.json")); + } + + ThemeConfig theme = JsonConfig.LoadTheme(themeId); + foreach (string imagePath in Directory.GetFiles("images", theme.imageFilename)) + { + File.Move(imagePath, + Path.Combine("themes", themeId, Path.GetFileName(imagePath))); + } + } + + if (Directory.GetFiles("images").Length == 0 && + Directory.GetDirectories("images").Length == 0) + { + Directory.Delete("images", false); + } + } + + // TODO Remove after 3.0 + private static void UpdateThemeImageLists() + { + List upgradeIds = new List() { "BitDay", "Earth_View", "Firewatch", + "New_York", "San_Francisco", "High_Sierra"}; + foreach (string filePath in Directory.EnumerateFiles("themes", "*.json", + SearchOption.AllDirectories)) + { + string themeId = Path.GetFileName(Path.GetDirectoryName(filePath)); + + if (!upgradeIds.Contains(themeId)) + { + continue; + } + + string jsonText = File.ReadAllText(filePath); + + if (!jsonText.Contains("sunriseImageList") || + !jsonText.Contains("sunsetImageList")) + { + jsonText = jsonText.Replace("}", + ",\"sunriseImageList\":[],\"sunsetImageList\":[]}"); + ThemeConfig theme = JsonConvert.DeserializeObject(jsonText); + + if (themeId == "BitDay") + { + theme.sunriseImageList = new int[] { 12, 1 }; + theme.dayImageList = new int[] { 2, 3, 4, 5, 6 }; + theme.sunsetImageList = new int[] { 7, 8 }; + theme.nightImageList = new int[] { 9, 10, 11 }; + } + else if (themeId == "Earth_View") + { + theme.sunriseImageList = new int[] { 4, 5, 6 }; + theme.dayImageList = new int[] { 7, 8, 9, 10, 11 }; + theme.sunsetImageList = new int[] { 12, 13, 14 }; + theme.nightImageList = new int[] { 15, 16, 1, 2, 3 }; + } + else if (themeId == "Firewatch") + { + theme.sunriseImageList = new int[] { 1, 2 }; + theme.dayImageList = new int[] { 3, 4, 5 }; + theme.sunsetImageList = new int[] { 6, 7 }; + theme.nightImageList = new int[] { 8 }; + } + else if (themeId == "New_York") + { + theme.sunriseImageList = new int[] { 1, 2, 3 }; + theme.dayImageList = new int[] { 4, 5, 6, 7, 8 }; + theme.sunsetImageList = new int[] { 9, 10, 11, 12 }; + theme.nightImageList = new int[] { 13, 14, 15, 16 }; + } + else if (themeId == "San_Francisco") + { + theme.sunriseImageList = new int[] { 2, 3, 4 }; + theme.dayImageList = new int[] { 5, 6, 7, 8, 9 }; + theme.sunsetImageList = new int[] { 10, 16, 11, 12 }; + theme.nightImageList = new int[] { 13, 14, 15, 1 }; + } + else if (themeId == "High_Sierra") + { + theme.sunriseImageList = new int[] { 3, 4, 5 }; + theme.dayImageList = new int[] { 6, 7, 8, 9, 10 }; + theme.sunsetImageList = new int[] { 9, 1, 12, 13 }; + theme.nightImageList = new int[] { 14, 15, 16, 2 }; + } + + string newJson = JsonConvert.SerializeObject(theme); + File.WriteAllText(filePath, newJson); + } + } + } + } +} diff --git a/src/ThemeDialog.cs b/src/ThemeDialog.cs index 9fbfb40..717173c 100644 --- a/src/ThemeDialog.cs +++ b/src/ThemeDialog.cs @@ -57,10 +57,10 @@ private Image GetThumbnailImage(ThemeConfig theme, int width, int height) return Image.FromFile(thumbnailPath); } - int imageId1 = theme.dayImageList[(theme.dayImageList.Length + 1) / 2]; + int imageId1 = theme.dayImageList[theme.dayImageList.Length / 2]; string imageFilename1 = theme.imageFilename.Replace("*", imageId1.ToString()); - int imageId2 = theme.nightImageList[(theme.nightImageList.Length + 1) / 2]; + int imageId2 = theme.nightImageList[theme.nightImageList.Length / 2]; string imageFilename2 = theme.imageFilename.Replace("*", imageId2.ToString()); using (var bmp1 = ShrinkImage(Path.Combine("themes", theme.themeId, imageFilename1), diff --git a/src/ThemeManager.cs b/src/ThemeManager.cs index aa520ba..65673b7 100644 --- a/src/ThemeManager.cs +++ b/src/ThemeManager.cs @@ -21,13 +21,8 @@ class ThemeManager public static void Initialize() { Directory.CreateDirectory("themes"); + Compatibility.CompatibilizeThemes(); - // TODO Remove after everyone has new file structure - if (Directory.Exists("images")) - { - UpdateThemeFileStructure(); - } - List themeIds = defaultThemes.ToList(); foreach (string filePath in Directory.EnumerateFiles("themes", "*.json", @@ -45,57 +40,26 @@ public static void Initialize() foreach (string themeId in themeIds) { - try - { - ThemeConfig theme = JsonConfig.LoadTheme(themeId); + //try + //{ + ThemeConfig theme = JsonConfig.LoadTheme(themeId); - themeSettings.Add(theme); + themeSettings.Add(theme); - if (theme.themeId == JsonConfig.settings.themeName) - { - currentTheme = theme; - } - } - catch + if (theme.themeId == JsonConfig.settings.themeName) { - DisableTheme(themeId); + currentTheme = theme; } + //} + //catch + //{ + // DisableTheme(themeId); + //} } DownloadMissingImages(FindMissingThemes()); } - private static void UpdateThemeFileStructure() - { - List filePaths = Directory.GetFiles("themes", "*.json").ToList(); - filePaths.AddRange(defaultThemes.Select( - themeId => Path.Combine("themes", themeId + ".json"))); - - foreach (string filePath in filePaths) - { - string themeId = Path.GetFileNameWithoutExtension(filePath); - Directory.CreateDirectory(Path.Combine("themes", themeId)); - - if (File.Exists(filePath)) - { - File.Move(filePath, Path.Combine("themes", themeId, "theme.json")); - } - - ThemeConfig theme = JsonConfig.LoadTheme(themeId); - foreach (string imagePath in Directory.GetFiles("images", theme.imageFilename)) - { - File.Move(imagePath, - Path.Combine("themes", themeId, Path.GetFileName(imagePath))); - } - } - - if (Directory.GetFiles("images").Length == 0 && - Directory.GetDirectories("images").Length == 0) - { - Directory.Delete("images", false); - } - } - public static void SelectTheme() { if (themeDialog == null) @@ -257,8 +221,8 @@ private static void DisableTheme(string themeId) Directory.Move(Path.Combine("themes", themeId), Path.Combine("themes", "." + themeId)); MessageBox.Show("The '" + themeId + "' theme could not be loaded and has been " + - "disabled. This is probably because it was developed for an older version of " + - "the app or its config file is formatted incorrectly.", "Error", + "disabled. This is probably because it was created for an older version of the " + + "app or its config file is formatted incorrectly.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } diff --git a/src/WinDynamicDesktop.csproj b/src/WinDynamicDesktop.csproj index 678f9f3..43f5c19 100644 --- a/src/WinDynamicDesktop.csproj +++ b/src/WinDynamicDesktop.csproj @@ -1,6 +1,6 @@  - + Debug @@ -38,8 +38,8 @@ WinDynamicDesktop.ico - - packages\Costura.Fody.3.2.2\lib\net40\Costura.dll + + packages\Costura.Fody.3.3.0\lib\net40\Costura.dll packages\DesktopBridge.Helpers.1.1\lib\net45\DesktopBridge.Helpers.dll @@ -47,8 +47,8 @@ packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - packages\RestSharp.106.6.3\lib\net452\RestSharp.dll + + packages\RestSharp.106.6.5\lib\net452\RestSharp.dll packages\SunCalcNet.1.0.2\lib\net461\SunCalcNet.dll @@ -84,6 +84,7 @@ AboutDialog.cs + Form @@ -166,7 +167,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/src/packages.config b/src/packages.config index eea2f93..9cfcd5e 100644 --- a/src/packages.config +++ b/src/packages.config @@ -1,9 +1,9 @@  - + - + \ No newline at end of file