diff --git a/Directory.Build.props b/Directory.Build.props
index 42daa2df7f..c19a55e8ea 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,5 +7,6 @@
false
false
False
+ 11
diff --git a/NOTICE.md b/NOTICE.md
index bd26b65d70..7083706c3e 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -81,14 +81,14 @@ A "contributor" is any person that distributes its contribution under this licen
https://github.com/wayland-project/wayland-protocols
-Copyright © 2008-2013 Kristian Høgsberg
-Copyright © 2010-2013 Intel Corporation
-Copyright © 2013 Rafael Antognolli
-Copyright © 2013 Jasper St. Pierre
-Copyright © 2014 Jonas Ådahl
-Copyright © 2014 Jason Ekstrand
-Copyright © 2014-2015 Collabora, Ltd.
-Copyright © 2015 Red Hat Inc.
+Copyright © 2008-2013 Kristian Høgsberg
+Copyright © 2010-2013 Intel Corporation
+Copyright © 2013 Rafael Antognolli
+Copyright © 2013 Jasper St. Pierre
+Copyright © 2014 Jonas Ådahl
+Copyright © 2014 Jason Ekstrand
+Copyright © 2014-2015 Collabora, Ltd.
+Copyright © 2015 Red Hat Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -140,7 +140,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
https://github.com/toptensoftware/RichTextKit
-Copyright © 2019 Topten Software. All Rights Reserved.
+Copyright © 2019 Topten Software. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this product except in compliance with the License. You may obtain
@@ -334,3 +334,31 @@ https://github.com/flutter/flutter
//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Reactive Extensions
+
+https://github.com/dotnet/reactive
+
+The MIT License (MIT)
+
+Copyright (c) .NET Foundation and Contributors
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/build/Base.props b/build/Base.props
index 433ce8e950..c2fc11c94b 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -2,6 +2,7 @@
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index e9c3d65b41..eca3ba37b0 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -8,7 +8,6 @@
https://github.com/AvaloniaUI/Avalonia/
true
$(NoWarn);CS1591
- preview
MIT
Icon.png
Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly.
diff --git a/global.json b/global.json
index e4a0cc20c2..8536535b51 100644
--- a/global.json
+++ b/global.json
@@ -4,6 +4,6 @@
"rollForward": "latestFeature"
},
"msbuild-sdks": {
- "Microsoft.Build.Traversal": "1.0.43"
+ "Microsoft.Build.Traversal": "3.2.0"
}
}
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index ace4a71a56..41d1534f8d 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -50,6 +50,7 @@
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; };
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; };
ED3791C42862E1F40080BD62 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */; };
+ EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -103,6 +104,7 @@
BC11A5BC2608D58F0017BAD0 /* automation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = automation.h; sourceTree = ""; };
BC11A5BD2608D58F0017BAD0 /* automation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = automation.mm; sourceTree = ""; };
ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
+ EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -163,6 +165,7 @@
1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */,
37A517B22159597E00FBA241 /* Screens.mm */,
37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
+ EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */,
AB7A61F02147C815003C5833 /* Products */,
AB661C1C2148230E00291242 /* Frameworks */,
18391676ECF0E983F4964357 /* WindowBaseImpl.mm */,
@@ -299,6 +302,7 @@
1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */,
18391AC16726CBC45856233B /* AvnWindow.mm in Sources */,
18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */,
+ EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm
index 6611dcc73f..d3b7b4ede6 100644
--- a/native/Avalonia.Native/src/OSX/AvnWindow.mm
+++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm
@@ -44,7 +44,7 @@
-(bool) isDialog
{
- return _parent->IsDialog();
+ return _parent->IsModal();
}
-(double) getExtendedTitleBarHeight
@@ -281,6 +281,9 @@
- (void)windowDidBecomeKey:(NSNotification *_Nonnull)notification
{
+ if (_parent == nullptr)
+ return;
+
_parent->BringToFront();
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/native/Avalonia.Native/src/OSX/PlatformSettings.mm b/native/Avalonia.Native/src/OSX/PlatformSettings.mm
new file mode 100644
index 0000000000..34ceb93186
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/PlatformSettings.mm
@@ -0,0 +1,113 @@
+#include "common.h"
+
+@interface CocoaThemeObserver : NSObject
+-(id)initWithCallback:(IAvnActionCallback *)callback;
+@end
+
+class PlatformSettings : public ComSingleObject
+{
+ CocoaThemeObserver* observer;
+
+public:
+ FORWARD_IUNKNOWN()
+ virtual AvnPlatformThemeVariant GetPlatformTheme() override
+ {
+ @autoreleasepool
+ {
+ if (@available(macOS 10.14, *))
+ {
+ if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAqua
+ || NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameVibrantLight) {
+ return AvnPlatformThemeVariant::Light;
+ } else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameDarkAqua
+ || NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameVibrantDark) {
+ return AvnPlatformThemeVariant::Dark;
+ } else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastAqua
+ || NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastVibrantLight) {
+ return AvnPlatformThemeVariant::HighContrastLight;
+ } else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastDarkAqua
+ || NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastVibrantDark) {
+ return AvnPlatformThemeVariant::HighContrastDark;
+ }
+ }
+ return AvnPlatformThemeVariant::Light;
+ }
+ }
+
+ virtual unsigned int GetAccentColor() override
+ {
+ @autoreleasepool
+ {
+ if (@available(macOS 10.14, *))
+ {
+ auto color = [NSColor controlAccentColor];
+ return to_argb(color);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+
+ virtual void RegisterColorsChange(IAvnActionCallback *callback) override
+ {
+ if (@available(macOS 10.14, *))
+ {
+ observer = [[CocoaThemeObserver alloc] initWithCallback: callback];
+ [[NSApplication sharedApplication] addObserver:observer forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nil];
+ }
+ }
+
+private:
+ unsigned int to_argb(NSColor* color)
+ {
+ const CGFloat* components = CGColorGetComponents(color.CGColor);
+ unsigned int alpha = static_cast(CGColorGetAlpha(color.CGColor) * 0xFF);
+ unsigned int red = static_cast(components[0] * 0xFF);
+ unsigned int green = static_cast(components[1] * 0xFF);
+ unsigned int blue = static_cast(components[2] * 0xFF);
+ return (alpha << 24) + (red << 16) + (green << 8) + blue;
+ }
+};
+
+@implementation CocoaThemeObserver
+{
+ ComPtr _callback;
+}
+- (id) initWithCallback:(IAvnActionCallback *)callback{
+ self = [super init];
+ if (self) {
+ _callback = callback;
+ }
+ return self;
+}
+
+/*- (void)didChangeValueForKey:(NSString *)key {
+ if([key isEqualToString:@"effectiveAppearance"]) {
+ _callback->Run();
+ }
+ else {
+ [super didChangeValueForKey:key];
+ }
+}*/
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+ ofObject:(id)object
+ change:(NSDictionary *)change
+ context:(void *)context {
+ if([keyPath isEqualToString:@"effectiveAppearance"]) {
+ _callback->Run();
+ } else {
+ [super observeValueForKeyPath:keyPath
+ ofObject:object
+ change:change
+ context:context];
+ }
+}
+@end
+
+extern IAvnPlatformSettings* CreatePlatformSettings()
+{
+ return new PlatformSettings();
+}
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
index 7fb002e54f..4c2758f6c6 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h
@@ -92,11 +92,13 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
+ virtual HRESULT SetFrameThemeVariant(AvnPlatformThemeVariant variant) override;
+
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard *clipboard, IAvnDndResultCallback *cb,
void *sourceHandle) override;
- virtual bool IsDialog();
+ virtual bool IsModal();
id GetWindowProtocol ();
diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
index 9946ad9b10..038e9a048c 100644
--- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
@@ -498,6 +498,24 @@ HRESULT WindowBaseImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
return S_OK;
}
+HRESULT WindowBaseImpl::SetFrameThemeVariant(AvnPlatformThemeVariant variant) {
+ START_COM_CALL;
+
+ NSAppearanceName appearanceName;
+ if (@available(macOS 10.14, *))
+ {
+ appearanceName = variant == AvnPlatformThemeVariant::Dark ? NSAppearanceNameDarkAqua : NSAppearanceNameAqua;
+ }
+ else
+ {
+ appearanceName = variant == AvnPlatformThemeVariant::Dark ? NSAppearanceNameVibrantDark : NSAppearanceNameAqua;
+ }
+
+ [Window setAppearance: [NSAppearance appearanceNamed: appearanceName]];
+
+ return S_OK;
+}
+
HRESULT WindowBaseImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard *clipboard, IAvnDndResultCallback *cb, void *sourceHandle) {
START_COM_CALL;
@@ -542,7 +560,7 @@ HRESULT WindowBaseImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, Av
return S_OK;
}
-bool WindowBaseImpl::IsDialog() {
+bool WindowBaseImpl::IsModal() {
return false;
}
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.h b/native/Avalonia.Native/src/OSX/WindowImpl.h
index b4b1d4e70b..3861aaf170 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.h
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.h
@@ -23,7 +23,7 @@ private:
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
- bool _isDialog;
+ bool _isModal;
WindowImpl* _parent;
std::list _children;
AvnExtendClientAreaChromeHints _extendClientHints;
@@ -91,7 +91,9 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetWindowState (AvnWindowState state) override;
- virtual bool IsDialog() override;
+ virtual bool IsModal() override;
+
+ bool IsOwned();
virtual void BringToFront () override;
diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm
index b6dacb6ce4..f345043f61 100644
--- a/native/Avalonia.Native/src/OSX/WindowImpl.mm
+++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm
@@ -63,7 +63,7 @@ HRESULT WindowImpl::Show(bool activate, bool isDialog) {
START_COM_CALL;
@autoreleasepool {
- _isDialog = isDialog || _parent != nullptr;
+ _isModal = isDialog;
WindowBaseImpl::Show(activate, isDialog);
@@ -97,7 +97,7 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) {
_parent = cparent;
- _isDialog = _parent != nullptr;
+ _isModal = _parent != nullptr;
if(_parent != nullptr && Window != nullptr){
// If one tries to show a child window with a minimized parent window, then the parent window will be
@@ -123,7 +123,7 @@ void WindowImpl::BringToFront()
{
if ([Window isVisible] && ![Window isMiniaturized])
{
- if(IsDialog())
+ if(IsModal())
{
Activate();
}
@@ -150,7 +150,7 @@ bool WindowImpl::CanBecomeKeyWindow()
{
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
- if((*iterator)->IsDialog())
+ if((*iterator)->IsModal())
{
return false;
}
@@ -569,8 +569,12 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) {
}
}
-bool WindowImpl::IsDialog() {
- return _isDialog;
+bool WindowImpl::IsModal() {
+ return _isModal;
+}
+
+bool WindowImpl::IsOwned() {
+ return _parent != nullptr;
}
NSWindowStyleMask WindowImpl::GetStyle() {
@@ -599,7 +603,7 @@ NSWindowStyleMask WindowImpl::GetStyle() {
break;
}
- if (!IsDialog()) {
+ if (!IsOwned()) {
s |= NSWindowStyleMaskMiniaturizable;
}
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index 7ee7205776..972927b99d 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -27,6 +27,7 @@ extern IAvnMenuItem* CreateAppMenuItem();
extern IAvnMenuItem* CreateAppMenuItemSeparator();
extern IAvnApplicationCommands* CreateApplicationCommands();
extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent);
+extern IAvnPlatformSettings* CreatePlatformSettings();
extern void SetAppMenu(IAvnMenu *menu);
extern void SetServicesMenu (IAvnMenu* menu);
extern IAvnMenu* GetAppMenu ();
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index c29d4108d0..99063e600e 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -398,6 +398,16 @@ public:
}
}
+ virtual HRESULT CreatePlatformSettings (IAvnPlatformSettings** ppv) override
+ {
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreatePlatformSettings();
+ return S_OK;
+ }
+ }
};
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index ca2d4b66ed..33f22f4d02 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -48,8 +48,12 @@
+
+ <_AvaloniaResourcesInputsCacheFilePath>$(IntermediateOutputPath)/Avalonia/Resources.Inputs.cache
+
+
-
+
@@ -57,7 +61,11 @@
-
+
+
+
+
+
-
+
+
+
+
@@ -103,6 +114,9 @@
File="$(AvaloniaXamlReferencesTemporaryFilePath)"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
+
+
+
+ DefaultCompileBindings="$(AvaloniaUseCompiledBindingsByDefault)">
+
+
diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs
index 7b8b27fff7..4d28f15e2c 100644
--- a/samples/ControlCatalog.Desktop/Program.cs
+++ b/samples/ControlCatalog.Desktop/Program.cs
@@ -23,7 +23,7 @@ namespace ControlCatalog
private static void ConfigureAssetAssembly(AppBuilder builder)
{
AvaloniaLocator.CurrentMutable
- .GetService()
+ .GetRequiredService()
.SetDefaultAssembly(typeof(App).Assembly);
}
}
diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs
index f3c1a68e72..1726028a3f 100644
--- a/samples/ControlCatalog/MainView.xaml.cs
+++ b/samples/ControlCatalog/MainView.xaml.cs
@@ -3,9 +3,11 @@ using System.Collections;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Immutable;
+using Avalonia.Platform;
using Avalonia.VisualTree;
using ControlCatalog.Models;
using ControlCatalog.Pages;
@@ -14,10 +16,14 @@ namespace ControlCatalog
{
public class MainView : UserControl
{
+ private readonly IPlatformSettings _platformSettings;
+
public MainView()
{
AvaloniaXamlLoader.Load(this);
-
+ _platformSettings = AvaloniaLocator.Current.GetRequiredService();
+ PlatformSettingsOnColorValuesChanged(_platformSettings, _platformSettings.GetColorValues());
+
var sideBar = this.Get("Sidebar");
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
@@ -37,6 +43,15 @@ namespace ControlCatalog
if (themes.SelectedItem is CatalogTheme theme)
{
App.SetThemeVariant(theme);
+
+ ((TopLevel?)this.GetVisualRoot())?.PlatformImpl?.SetFrameThemeVariant(theme switch
+ {
+ CatalogTheme.FluentLight => PlatformThemeVariant.Light,
+ CatalogTheme.FluentDark => PlatformThemeVariant.Dark,
+ CatalogTheme.SimpleLight => PlatformThemeVariant.Light,
+ CatalogTheme.SimpleDark => PlatformThemeVariant.Dark,
+ _ => throw new ArgumentOutOfRangeException()
+ });
}
};
@@ -89,6 +104,62 @@ namespace ControlCatalog
var decorations = this.Get("Decorations");
if (VisualRoot is Window window)
decorations.SelectedIndex = (int)window.SystemDecorations;
+
+ _platformSettings.ColorValuesChanged += PlatformSettingsOnColorValuesChanged;
+ PlatformSettingsOnColorValuesChanged(_platformSettings, _platformSettings.GetColorValues());
+ }
+
+ protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromLogicalTree(e);
+
+ _platformSettings.ColorValuesChanged -= PlatformSettingsOnColorValuesChanged;
+ }
+
+ private void PlatformSettingsOnColorValuesChanged(object? sender, PlatformColorValues e)
+ {
+ var themes = this.Get("Themes");
+ var currentTheme = (CatalogTheme?)themes.SelectedItem ?? CatalogTheme.FluentLight;
+ var newTheme = (currentTheme, e.ThemeVariant) switch
+ {
+ (CatalogTheme.FluentDark, PlatformThemeVariant.Light) => CatalogTheme.FluentLight,
+ (CatalogTheme.FluentLight, PlatformThemeVariant.Dark) => CatalogTheme.FluentDark,
+ (CatalogTheme.SimpleDark, PlatformThemeVariant.Light) => CatalogTheme.SimpleLight,
+ (CatalogTheme.SimpleLight, PlatformThemeVariant.Dark) => CatalogTheme.SimpleDark,
+ _ => currentTheme
+ };
+ themes.SelectedItem = newTheme;
+
+ Application.Current!.Resources["SystemAccentColor"] = e.AccentColor1;
+ Application.Current.Resources["SystemAccentColorDark1"] = ChangeColorLuminosity(e.AccentColor1, -0.3);
+ Application.Current.Resources["SystemAccentColorDark2"] = ChangeColorLuminosity(e.AccentColor1, -0.5);
+ Application.Current.Resources["SystemAccentColorDark3"] = ChangeColorLuminosity(e.AccentColor1, -0.7);
+ Application.Current.Resources["SystemAccentColorLight1"] = ChangeColorLuminosity(e.AccentColor1, -0.3);
+ Application.Current.Resources["SystemAccentColorLight2"] = ChangeColorLuminosity(e.AccentColor1, -0.5);
+ Application.Current.Resources["SystemAccentColorLight3"] = ChangeColorLuminosity(e.AccentColor1, -0.7);
+
+ static Color ChangeColorLuminosity(Color color, double luminosityFactor)
+ {
+ var red = (double)color.R;
+ var green = (double)color.G;
+ var blue = (double)color.B;
+
+ if (luminosityFactor < 0)
+ {
+ luminosityFactor = 1 + luminosityFactor;
+ red *= luminosityFactor;
+ green *= luminosityFactor;
+ blue *= luminosityFactor;
+ }
+ else if (luminosityFactor >= 0)
+ {
+ red = (255 - red) * luminosityFactor + red;
+ green = (255 - green) * luminosityFactor + green;
+ blue = (255 - blue) * luminosityFactor + blue;
+ }
+
+ return new Color(color.A, (byte)red, (byte)green, (byte)blue);
+ }
}
}
}
diff --git a/samples/ControlCatalog/Models/StateData.cs b/samples/ControlCatalog/Models/StateData.cs
index bd6d186252..a7ea655cd2 100644
--- a/samples/ControlCatalog/Models/StateData.cs
+++ b/samples/ControlCatalog/Models/StateData.cs
@@ -6,10 +6,10 @@ public class StateData
public string Abbreviation { get; private set; }
public string Capital { get; private set; }
- public StateData(string name, string abbreviatoin, string capital)
+ public StateData(string name, string abbreviation, string capital)
{
Name = name;
- Abbreviation = abbreviatoin;
+ Abbreviation = abbreviation;
Capital = capital;
}
@@ -17,4 +17,4 @@ public class StateData
{
return Name;
}
-}
\ No newline at end of file
+}
diff --git a/samples/ControlCatalog/Pages/CarouselPage.xaml b/samples/ControlCatalog/Pages/CarouselPage.xaml
index 1c2d768966..352fa32e30 100644
--- a/samples/ControlCatalog/Pages/CarouselPage.xaml
+++ b/samples/ControlCatalog/Pages/CarouselPage.xaml
@@ -12,7 +12,7 @@
-
+
@@ -35,7 +35,7 @@
Orientation
-
+
Horizontal
Vertical
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index cc23ef796a..5325534909 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -46,7 +46,7 @@
Classes="h2"
IsVisible="False"
Text="Last picker results:" />
-
+
("PickerLastResults");
+ var results = this.Get("PickerLastResults");
var resultsVisible = this.Get("PickerLastResultsVisible");
var bookmarkContainer = this.Get("BookmarkContainer");
var openedFileContent = this.Get("OpenedFileContent");
@@ -36,18 +36,18 @@ namespace ControlCatalog.Pages
{
if (this.Get("UseFilters").IsChecked != true)
return new List();
- return new List
- {
- new FileDialogFilter
- {
- Name = "Text files (.txt)", Extensions = new List {"txt"}
- },
- new FileDialogFilter
- {
- Name = "All files",
- Extensions = new List {"*"}
- }
- };
+ return new List
+ {
+ new FileDialogFilter
+ {
+ Name = "Text files (.txt)", Extensions = new List {"txt"}
+ },
+ new FileDialogFilter
+ {
+ Name = "All files",
+ Extensions = new List {"*"}
+ }
+ };
}
List? GetFileTypes()
@@ -55,10 +55,10 @@ namespace ControlCatalog.Pages
if (this.Get("UseFilters").IsChecked != true)
return null;
return new List
- {
- FilePickerFileTypes.All,
- FilePickerFileTypes.TextPlain
- };
+ {
+ FilePickerFileTypes.All,
+ FilePickerFileTypes.TextPlain
+ };
}
this.Get