From 15d4bf6bd77411af7f5372156678a038e0144498 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Cassettari Date: Sat, 6 Jul 2024 12:20:35 -0300 Subject: [PATCH] Add `RibbonThemeUtils` for ThemeChanged --- CHANGELOG.md | 5 + Directory.Build.props | 2 +- .../ricaun.Revit.UI.Example.csproj | 4 +- .../Themes/RibbonThemeUtilsTests.cs | 39 ++++++ .../ricaun.Revit.UI.Tests.csproj | 2 +- ricaun.Revit.UI/Utils/RibbonThemeUtils.cs | 122 ++++++++++++++++++ ricaun.Revit.UI/ricaun.Revit.UI.csproj | 14 +- 7 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 ricaun.Revit.UI.Tests/Themes/RibbonThemeUtilsTests.cs create mode 100644 ricaun.Revit.UI/Utils/RibbonThemeUtils.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index f4fda36..1b3dc31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.6.3] / 2024-07-06 ### Features +- `RibbonThemeUtils` to change the theme of the Ribbon. (Revit 2019+) +- Set project configuration to support `net47` and `net48`. ### Updated - Change `GetRibbonItem` to `GetRibbonItem_Alternative` to fix null when panel is removed. +### Tests +- Add `RibbonThemeUtilsTests` to test the theme change event. ## [0.6.2] / 2024-01-09 - 2024-02-05 ### Features @@ -342,6 +346,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - First Release [vNext]: ../../compare/1.0.0...HEAD +[0.6.3]: ../../compare/0.6.2...0.6.3 [0.6.2]: ../../compare/0.6.1...0.6.2 [0.6.1]: ../../compare/0.6.0...0.6.1 [0.6.0]: ../../compare/0.5.7...0.6.0 diff --git a/Directory.Build.props b/Directory.Build.props index 00707fa..2738030 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - 0.6.3-alpha + 0.6.3-beta \ No newline at end of file diff --git a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj index d02d1cf..9acb41e 100644 --- a/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj +++ b/ricaun.Revit.UI.Example/ricaun.Revit.UI.Example.csproj @@ -13,12 +13,12 @@ - net46;net8.0-windows + net48;net8.0-windows - 2017 + 2021 diff --git a/ricaun.Revit.UI.Tests/Themes/RibbonThemeUtilsTests.cs b/ricaun.Revit.UI.Tests/Themes/RibbonThemeUtilsTests.cs new file mode 100644 index 0000000..337eec5 --- /dev/null +++ b/ricaun.Revit.UI.Tests/Themes/RibbonThemeUtilsTests.cs @@ -0,0 +1,39 @@ +using ricaun.Revit.UI.Utils; +using NUnit.Framework; +using System; + +namespace ricaun.Revit.UI.Tests.Themes +{ + public class RibbonThemeUtilsTests + { + [Test] + public void RibbonThemeUtils_ThemeChangedEventHandler() + { + bool themeChanged = false; + ThemeChangedEventHandler RibbonThemeUtils_ThemeChanged = (object sender, ThemeChangedEventArgs e) => + { + themeChanged = true; + Console.WriteLine($"ThemeChangedEvent {e.IsLight}"); + }; + + try + { + RibbonThemeUtils.ThemeChanged += RibbonThemeUtils_ThemeChanged; + RibbonThemeUtils.ThemeChangedTest(); + Assert.IsTrue(themeChanged); + } + finally + { + RibbonThemeUtils.ThemeChanged -= RibbonThemeUtils_ThemeChanged; + } + } + + [Test] + public void ThemeChangedEventArgs_Constructor() + { + var themeChangedEventArgs = new ThemeChangedEventArgs(true); + Assert.IsTrue(themeChangedEventArgs.IsLight); + Assert.IsFalse(themeChangedEventArgs.IsDark); + } + } +} diff --git a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj index c98b3ea..d309f72 100644 --- a/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj +++ b/ricaun.Revit.UI.Tests/ricaun.Revit.UI.Tests.csproj @@ -42,7 +42,7 @@ - + diff --git a/ricaun.Revit.UI/Utils/RibbonThemeUtils.cs b/ricaun.Revit.UI/Utils/RibbonThemeUtils.cs new file mode 100644 index 0000000..92fc66b --- /dev/null +++ b/ricaun.Revit.UI/Utils/RibbonThemeUtils.cs @@ -0,0 +1,122 @@ + +using System; + +namespace ricaun.Revit.UI.Utils +{ + /// + /// ThemeChangedEventArgs + /// + public sealed class ThemeChangedEventArgs : System.EventArgs + { + internal ThemeChangedEventArgs(bool isLight) + { + IsLight = isLight; + } + /// + /// Theme is Light + /// + public bool IsLight { get; private set; } + /// + /// Theme is Dark + /// + public bool IsDark => !IsLight; + } + /// + /// ThemeChangedEventHandler for RibbonThemeUtils + /// + /// + /// + + public delegate void ThemeChangedEventHandler(object sender, ThemeChangedEventArgs e); + /// + /// RibbonThemeUtils using UIFramework.ApplicationTheme + /// + /// + /// Available for Revit 2019+ + /// + public class RibbonThemeUtils + { + /// + /// ThemeChanged + /// + public static event ThemeChangedEventHandler ThemeChanged; + /// + /// Theme is Light + /// + public static bool IsLight { get; private set; } = true; + /// + /// Theme is Dark + /// + public bool IsDark => !IsLight; + +#if NET47_OR_GREATER || NET + static RibbonThemeUtils() + { + ExecuteCurrentTheme(); + UIFramework.ApplicationTheme.CurrentTheme.PropertyChanged += CurrentTheme_PropertyChanged; + } + + internal static void Dispose() + { + UIFramework.ApplicationTheme.CurrentTheme.PropertyChanged -= CurrentTheme_PropertyChanged; + ThemeChanged = null; + } + + internal static void ThemeChangedTest() + { + UIFramework.RevitRibbonControl.RibbonControl.Dispatcher.Invoke(() => + { + var color = UIFramework.ApplicationTheme.CurrentTheme.ActiveTabBackgroundColor; + UIFramework.ApplicationTheme.CurrentTheme.ActiveTabBackgroundColor = System.Windows.Media.Colors.White; + UIFramework.ApplicationTheme.CurrentTheme.ActiveTabBackgroundColor = System.Windows.Media.Colors.Black; + UIFramework.ApplicationTheme.CurrentTheme.ActiveTabBackgroundColor = color; + }); + } + + private static void ExecuteCurrentTheme() + { + if (IsThemeChanged(out UIFramework.ApplicationTheme theme, out bool isLight)) + { + ExecuteThemeChanged(theme, isLight); + } + } + + const string ApplicationCurrentThemeChangedPropertyName = "ActiveTabBackgroundColor"; + private static void CurrentTheme_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == ApplicationCurrentThemeChangedPropertyName) + { + ExecuteCurrentTheme(); + } + } + private static void ExecuteThemeChanged(UIFramework.ApplicationTheme theme, bool isLight) + { + try + { + ThemeChanged?.Invoke(theme, new ThemeChangedEventArgs(IsLight)); + } + catch { } + } + private static bool IsThemeChanged(out UIFramework.ApplicationTheme theme, out bool isLight) + { + theme = UIFramework.ApplicationTheme.CurrentTheme; + isLight = IsThemeLight(theme); + + if (isLight == IsLight) + return false; + + IsLight = isLight; + return true; + } + private static bool IsThemeLight(UIFramework.ApplicationTheme applicationTheme) + { + if (applicationTheme is null) + return true; + + var color = applicationTheme.ActiveTabBackgroundColor; + var brightness = (byte)((color.R + color.G + color.B) / 3); + return brightness > 128; + } +#endif + } +} diff --git a/ricaun.Revit.UI/ricaun.Revit.UI.csproj b/ricaun.Revit.UI/ricaun.Revit.UI.csproj index 6ff7924..b7b5e86 100644 --- a/ricaun.Revit.UI/ricaun.Revit.UI.csproj +++ b/ricaun.Revit.UI/ricaun.Revit.UI.csproj @@ -13,14 +13,24 @@ - net46;net8.0-windows + net46;net47;net48;net8.0-windows - + 2017 + + + 2019 + + + + + 2021 + + 2025