diff --git a/src/Compatibility/ControlGallery/src/Android/AttachedStateEffectRenderer.cs b/src/Compatibility/ControlGallery/src/Android/AttachedStateEffectRenderer.cs index ac86a75eaa31..7c4ae43cdb1d 100644 --- a/src/Compatibility/ControlGallery/src/Android/AttachedStateEffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/Android/AttachedStateEffectRenderer.cs @@ -4,6 +4,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery.Android; using Microsoft.Maui.Controls.Compatibility.ControlGallery.Effects; using Microsoft.Maui.Controls.Compatibility.Platform.Android; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(AttachedStateEffectRenderer), AttachedStateEffect.EffectName)] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.Android diff --git a/src/Compatibility/ControlGallery/src/Android/BorderEffect.cs b/src/Compatibility/ControlGallery/src/Android/BorderEffect.cs index c30769da9e3b..a6cb57b0b999 100644 --- a/src/Compatibility/ControlGallery/src/Android/BorderEffect.cs +++ b/src/Compatibility/ControlGallery/src/Android/BorderEffect.cs @@ -1,4 +1,5 @@ using Microsoft.Maui.Controls.Compatibility.Platform.Android; +using Microsoft.Maui.Controls.Platform; namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.Android { diff --git a/src/Compatibility/ControlGallery/src/Android/ContentDescriptionEffectRenderer.cs b/src/Compatibility/ControlGallery/src/Android/ContentDescriptionEffectRenderer.cs index d8a89e35b237..8c485c0e566e 100644 --- a/src/Compatibility/ControlGallery/src/Android/ContentDescriptionEffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/Android/ContentDescriptionEffectRenderer.cs @@ -6,6 +6,7 @@ using Microsoft.Maui.Controls.Compatibility.Platform.Android; using AndroidX.Core.View; using AndroidX.Core.View.Accessibility; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(ContentDescriptionEffectRenderer), ContentDescriptionEffect.EffectName)] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.Android diff --git a/src/Compatibility/ControlGallery/src/Android/RippleEffect.cs b/src/Compatibility/ControlGallery/src/Android/RippleEffect.cs index 51cd915eb038..a47d4fd11afe 100644 --- a/src/Compatibility/ControlGallery/src/Android/RippleEffect.cs +++ b/src/Compatibility/ControlGallery/src/Android/RippleEffect.cs @@ -3,6 +3,7 @@ using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Compatibility.Platform.Android; using AView = Android.Views.View; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(Microsoft.Maui.Controls.Compatibility.ControlGallery.Android.RippleEffect), nameof(Microsoft.Maui.Controls.Compatibility.ControlGallery.Android.RippleEffect))] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.Android diff --git a/src/Compatibility/ControlGallery/src/Android/_58406EffectRenderer.cs b/src/Compatibility/ControlGallery/src/Android/_58406EffectRenderer.cs index a6e1fefad52d..49b556c88cec 100644 --- a/src/Compatibility/ControlGallery/src/Android/_58406EffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/Android/_58406EffectRenderer.cs @@ -5,6 +5,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Compatibility.ControlGallery.Issues; using Microsoft.Maui.Controls.Compatibility.Platform.Android; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(Microsoft.Maui.Controls.Compatibility.ControlGallery.Android._58406EffectRenderer), Bugzilla58406.EffectName)] diff --git a/src/Compatibility/ControlGallery/src/Core/Startup.cs b/src/Compatibility/ControlGallery/src/Core/Startup.cs index f792b1fb11ad..308c1f1dd206 100644 --- a/src/Compatibility/ControlGallery/src/Core/Startup.cs +++ b/src/Compatibility/ControlGallery/src/Core/Startup.cs @@ -29,6 +29,10 @@ public virtual void Configure(IAppHostBuilder appBuilder) .ConfigureServices(services => { DependencyService.Register(Device.GetAssemblies()); + }) + .ConfigureEffects(effects => + { + effects.AddCompatibilityEffects(Device.GetAssemblies()); }); } } diff --git a/src/Compatibility/ControlGallery/src/WinUI/AttachedStateEffectRenderer.cs b/src/Compatibility/ControlGallery/src/WinUI/AttachedStateEffectRenderer.cs index 43b6b4bc4b5f..842bd5f040e4 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/AttachedStateEffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/WinUI/AttachedStateEffectRenderer.cs @@ -4,6 +4,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery.Effects; using Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI; using Microsoft.Maui.Controls.Compatibility.Platform.UWP; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(AttachedStateEffectRenderer), AttachedStateEffect.EffectName)] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI diff --git a/src/Compatibility/ControlGallery/src/WinUI/BorderEffect.cs b/src/Compatibility/ControlGallery/src/WinUI/BorderEffect.cs index 3f905b87f111..2ec9fce0667c 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/BorderEffect.cs +++ b/src/Compatibility/ControlGallery/src/WinUI/BorderEffect.cs @@ -1,6 +1,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI; using Microsoft.Maui.Controls.Compatibility.Platform.UWP; +using Microsoft.Maui.Controls.Platform; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; diff --git a/src/Compatibility/ControlGallery/src/WinUI/FocusEffect.cs b/src/Compatibility/ControlGallery/src/WinUI/FocusEffect.cs index f69fa91ac690..d7fc3ee5577c 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/FocusEffect.cs +++ b/src/Compatibility/ControlGallery/src/WinUI/FocusEffect.cs @@ -7,6 +7,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI; using Microsoft.Maui.Controls.Compatibility.Platform.UWP; +using Microsoft.Maui.Controls.Platform; using Microsoft.UI; using Microsoft.UI.Xaml.Media; using Windows.UI; diff --git a/src/Compatibility/ControlGallery/src/WinUI/_58406EffectRenderer.cs b/src/Compatibility/ControlGallery/src/WinUI/_58406EffectRenderer.cs index 10e84a8155c0..991d11c30727 100644 --- a/src/Compatibility/ControlGallery/src/WinUI/_58406EffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/WinUI/_58406EffectRenderer.cs @@ -2,6 +2,7 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Compatibility.ControlGallery.Issues; using Microsoft.Maui.Controls.Compatibility.Platform.UWP; +using Microsoft.Maui.Controls.Platform; using Microsoft.UI.Xaml.Controls; [assembly: ExportEffect(typeof(Microsoft.Maui.Controls.Compatibility.ControlGallery.WinUI._58406EffectRenderer), Bugzilla58406.EffectName)] diff --git a/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs b/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs index a4e9f0abac93..7da514d17287 100644 --- a/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs +++ b/src/Compatibility/ControlGallery/src/iOS/AppDelegate.cs @@ -14,6 +14,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; using Size = Microsoft.Maui.Graphics.Size; +using Microsoft.Maui.Controls.Platform; [assembly: Dependency(typeof(TestCloudService))] [assembly: Dependency(typeof(CacheService))] diff --git a/src/Compatibility/ControlGallery/src/iOS/AttachedStateEffectRenderer.cs b/src/Compatibility/ControlGallery/src/iOS/AttachedStateEffectRenderer.cs index 659283ae4483..308e7e9eb03a 100644 --- a/src/Compatibility/ControlGallery/src/iOS/AttachedStateEffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/iOS/AttachedStateEffectRenderer.cs @@ -5,6 +5,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery.Effects; using Microsoft.Maui.Controls.Compatibility; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(AttachedStateEffectRenderer), AttachedStateEffect.EffectName)] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS diff --git a/src/Compatibility/ControlGallery/src/iOS/CustomEffects/FooEffect.cs b/src/Compatibility/ControlGallery/src/iOS/CustomEffects/FooEffect.cs index 7318c9345fce..2ceea553dbda 100644 --- a/src/Compatibility/ControlGallery/src/iOS/CustomEffects/FooEffect.cs +++ b/src/Compatibility/ControlGallery/src/iOS/CustomEffects/FooEffect.cs @@ -1,5 +1,6 @@ using Microsoft.Maui.Controls; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS.CustomEffects.FooEffect), nameof(Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS.CustomEffects.FooEffect))] diff --git a/src/Compatibility/ControlGallery/src/iOS/CustomEffects/GradientEffect.cs b/src/Compatibility/ControlGallery/src/iOS/CustomEffects/GradientEffect.cs index d2d4a70b6153..c8903c84d041 100644 --- a/src/Compatibility/ControlGallery/src/iOS/CustomEffects/GradientEffect.cs +++ b/src/Compatibility/ControlGallery/src/iOS/CustomEffects/GradientEffect.cs @@ -6,6 +6,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS; using Microsoft.Maui.Controls.Compatibility.ControlGallery.Issues; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(GradientEffect), Issue6334.EffectName)] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS diff --git a/src/Compatibility/ControlGallery/src/iOS/SearchbarEffect.cs b/src/Compatibility/ControlGallery/src/iOS/SearchbarEffect.cs index bbb1935823cf..e54b52671426 100644 --- a/src/Compatibility/ControlGallery/src/iOS/SearchbarEffect.cs +++ b/src/Compatibility/ControlGallery/src/iOS/SearchbarEffect.cs @@ -5,6 +5,7 @@ using Microsoft.Maui.Controls.Compatibility; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; using Microsoft.Maui.Graphics; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(SearchbarEffect), "SearchbarEffect")] namespace Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS diff --git a/src/Compatibility/ControlGallery/src/iOS/_58406EffectRenderer.cs b/src/Compatibility/ControlGallery/src/iOS/_58406EffectRenderer.cs index f7c61565ff3c..945c2954bc35 100644 --- a/src/Compatibility/ControlGallery/src/iOS/_58406EffectRenderer.cs +++ b/src/Compatibility/ControlGallery/src/iOS/_58406EffectRenderer.cs @@ -4,6 +4,7 @@ using Microsoft.Maui.Controls.Compatibility.ControlGallery.Issues; using Microsoft.Maui.Controls.Compatibility; using Microsoft.Maui.Controls.Compatibility.Platform.iOS; +using Microsoft.Maui.Controls.Platform; [assembly: ExportEffect(typeof(Microsoft.Maui.Controls.Compatibility.ControlGallery.iOS._58406EffectRenderer), Bugzilla58406.EffectName)] diff --git a/src/Compatibility/Core/src/Android/FastRenderers/EffectControlProvider.cs b/src/Compatibility/Core/src/Android/FastRenderers/EffectControlProvider.cs index 09facf09f506..c4392bd09ef3 100644 --- a/src/Compatibility/Core/src/Android/FastRenderers/EffectControlProvider.cs +++ b/src/Compatibility/Core/src/Android/FastRenderers/EffectControlProvider.cs @@ -1,4 +1,5 @@ using Android.Views; +using Microsoft.Maui.Controls.Platform; using AView = Android.Views.View; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers @@ -28,8 +29,8 @@ public void RegisterEffect(Effect effect) return; } - platformEffect.SetControl(_control); - platformEffect.SetContainer(_container); + platformEffect.Container = _container; + platformEffect.Control = _control; } } } \ No newline at end of file diff --git a/src/Compatibility/Core/src/Android/PlatformEffect.cs b/src/Compatibility/Core/src/Android/PlatformEffect.cs deleted file mode 100644 index 021eb9457474..000000000000 --- a/src/Compatibility/Core/src/Android/PlatformEffect.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using Android.Views; -using AView = Android.Views.View; - -namespace Microsoft.Maui.Controls.Compatibility.Platform.Android -{ - public abstract class PlatformEffect : PlatformEffect - { - } -} \ No newline at end of file diff --git a/src/Compatibility/Core/src/Android/Renderers/RefreshViewRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/RefreshViewRenderer.cs index 63fe55349948..73648ed0251a 100644 --- a/src/Compatibility/Core/src/Android/Renderers/RefreshViewRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/RefreshViewRenderer.cs @@ -272,8 +272,8 @@ void IEffectControlProvider.RegisterEffect(Effect effect) void OnRegisterEffect(PlatformEffect effect) { - effect.SetContainer(this); - effect.SetControl(this); + effect.Container = this; + effect.Control = this; } } } \ No newline at end of file diff --git a/src/Compatibility/Core/src/Android/Renderers/ScrollViewRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/ScrollViewRenderer.cs index dffc8d9a3062..9d8c9d4cb16a 100644 --- a/src/Compatibility/Core/src/Android/Renderers/ScrollViewRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/ScrollViewRenderer.cs @@ -318,8 +318,8 @@ void IEffectControlProvider.RegisterEffect(Effect effect) void OnRegisterEffect(PlatformEffect effect) { - effect.SetContainer(this); - effect.SetControl(this); + effect.Container = this; + effect.Control = this; } static int GetDistance(double start, double position, double v) diff --git a/src/Compatibility/Core/src/Android/ViewRenderer.cs b/src/Compatibility/Core/src/Android/ViewRenderer.cs index 06a5efddc9ae..1050208f2309 100644 --- a/src/Compatibility/Core/src/Android/ViewRenderer.cs +++ b/src/Compatibility/Core/src/Android/ViewRenderer.cs @@ -198,7 +198,7 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b) protected override void OnRegisterEffect(PlatformEffect effect) { base.OnRegisterEffect(effect); - effect.SetControl(Control); + effect.Control = Control; } void SetupAutomationDefaults() diff --git a/src/Compatibility/Core/src/Android/VisualElementRenderer.cs b/src/Compatibility/Core/src/Android/VisualElementRenderer.cs index 6032fd0fbfb4..48b18b759361 100644 --- a/src/Compatibility/Core/src/Android/VisualElementRenderer.cs +++ b/src/Compatibility/Core/src/Android/VisualElementRenderer.cs @@ -412,7 +412,7 @@ void UpdateParentPageTraversalOrder() protected virtual void OnRegisterEffect(PlatformEffect effect) { - effect.SetContainer(this); + effect.Container = this; } void SetupAutomationDefaults() diff --git a/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs b/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs index d71a032c863e..7028afb6bb19 100644 --- a/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs +++ b/src/Compatibility/Core/src/MauiHandlersCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.Maui.Controls.Hosting; using Microsoft.Maui.Hosting; namespace Microsoft.Maui.Controls.Compatibility @@ -101,5 +102,13 @@ public static IImageSourceServiceCollection AddCompatibilityServices(this IImage #endif return services; } + + + + public static IEffectsBuilder AddCompatibilityEffects(this IEffectsBuilder effectsBuilder, params global::System.Reflection.Assembly[] assemblies) + { + Internals.Registrar.RegisterEffects(assemblies); + return effectsBuilder; + } } } \ No newline at end of file diff --git a/src/Compatibility/Core/src/WinUI/PlatformEffect.cs b/src/Compatibility/Core/src/WinUI/PlatformEffect.cs deleted file mode 100644 index b99880be2d64..000000000000 --- a/src/Compatibility/Core/src/WinUI/PlatformEffect.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.UI.Xaml; - -namespace Microsoft.Maui.Controls.Compatibility.Platform.UWP -{ - public abstract class PlatformEffect : PlatformEffect - { - } -} \ No newline at end of file diff --git a/src/Compatibility/Core/src/WinUI/VisualElementRenderer.cs b/src/Compatibility/Core/src/WinUI/VisualElementRenderer.cs index 645525c6cf1d..24a3ca38c461 100644 --- a/src/Compatibility/Core/src/WinUI/VisualElementRenderer.cs +++ b/src/Compatibility/Core/src/WinUI/VisualElementRenderer.cs @@ -397,10 +397,11 @@ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEv protected virtual void OnRegisterEffect(PlatformEffect effect) { - effect.SetContainer(this); - effect.SetControl(Control); + effect.Container = this; + effect.Control = Control; } + protected virtual void SetAutomationId(string id) { this.SetAutomationPropertiesAutomationId(id); diff --git a/src/Compatibility/Core/src/iOS/PlatformEffect.cs b/src/Compatibility/Core/src/iOS/PlatformEffect.cs deleted file mode 100644 index c668a4fc0192..000000000000 --- a/src/Compatibility/Core/src/iOS/PlatformEffect.cs +++ /dev/null @@ -1,13 +0,0 @@ -#if __MOBILE__ -using UIKit; -namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS -#else -using UIView = AppKit.NSView; - -namespace Microsoft.Maui.Controls.Compatibility.Platform.MacOS -#endif -{ - public abstract class PlatformEffect : PlatformEffect - { - } -} \ No newline at end of file diff --git a/src/Compatibility/Core/src/iOS/ShadowEffect.cs b/src/Compatibility/Core/src/iOS/ShadowEffect.cs index d948678b1dda..14cf6eeca303 100644 --- a/src/Compatibility/Core/src/iOS/ShadowEffect.cs +++ b/src/Compatibility/Core/src/iOS/ShadowEffect.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Platform; using Microsoft.Maui.Graphics; using UIKit; using PlatformElement = Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.VisualElement; diff --git a/src/Compatibility/Core/src/iOS/ViewRenderer.cs b/src/Compatibility/Core/src/iOS/ViewRenderer.cs index d98b5fa96c67..76ce558b3e9d 100644 --- a/src/Compatibility/Core/src/iOS/ViewRenderer.cs +++ b/src/Compatibility/Core/src/iOS/ViewRenderer.cs @@ -169,7 +169,7 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE protected override void OnRegisterEffect(PlatformEffect effect) { base.OnRegisterEffect(effect); - effect.SetControl(Control); + effect.Control = Control; } protected override void SetAccessibilityHint() diff --git a/src/Compatibility/Core/src/iOS/VisualElementRenderer.cs b/src/Compatibility/Core/src/iOS/VisualElementRenderer.cs index f270c937d87a..d5f782907a84 100644 --- a/src/Compatibility/Core/src/iOS/VisualElementRenderer.cs +++ b/src/Compatibility/Core/src/iOS/VisualElementRenderer.cs @@ -108,8 +108,8 @@ public static void RegisterEffect(Effect effect, NativeView container, NativeVie if (platformEffect == null) return; - platformEffect.SetContainer(container); - platformEffect.SetControl(control); + platformEffect.Container = container; + platformEffect.Control = control; } #if __MOBILE__ @@ -445,7 +445,7 @@ protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEv protected virtual void OnRegisterEffect(PlatformEffect effect) { - effect.SetContainer(this); + effect.Container = this; } protected virtual void SetAccessibilityHint() diff --git a/src/Controls/samples/Controls.Sample/Maui.Controls.Sample-net6.csproj b/src/Controls/samples/Controls.Sample/Maui.Controls.Sample-net6.csproj index 83cab6080050..36db1a2fee16 100644 --- a/src/Controls/samples/Controls.Sample/Maui.Controls.Sample-net6.csproj +++ b/src/Controls/samples/Controls.Sample/Maui.Controls.Sample-net6.csproj @@ -54,7 +54,6 @@ - diff --git a/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml b/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml new file mode 100644 index 000000000000..92aec89c03c9 --- /dev/null +++ b/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml @@ -0,0 +1,32 @@ + + + + + + + \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml.cs b/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml.cs new file mode 100644 index 000000000000..3f3320b967db --- /dev/null +++ b/src/Controls/samples/Controls.Sample/Pages/Core/EffectsPage.xaml.cs @@ -0,0 +1,139 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using Microsoft.Maui; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Controls.Platform; + +namespace Maui.Controls.Sample.Pages +{ + public partial class EffectsPage + { + public EffectsPage() + { + InitializeComponent(); + } + } + + public class FocusRoutingEffect : RoutingEffect + { + } + +#if WINDOWS + public class FocusPlatformEffect : PlatformEffect + { + public FocusPlatformEffect() : base() + { + } + + protected override void OnAttached() + { + try + { + (Control as Microsoft.UI.Xaml.Controls.Control).Background = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Cyan); + (Control as MauiTextBox).BackgroundFocusBrush = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.White); + } + catch (Exception ex) + { + Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message); + } + + } + + protected override void OnDetached() + { + } + } +#elif __ANDROID__ + public class FocusPlatformEffect : PlatformEffect + { + Android.Graphics.Color originalBackgroundColor = new Android.Graphics.Color(0, 0, 0, 0); + Android.Graphics.Color backgroundColor; + + protected override void OnAttached() + { + try + { + backgroundColor = Android.Graphics.Color.LightGreen; + Control.SetBackgroundColor(backgroundColor); + } + catch (Exception ex) + { + Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); + } + } + + protected override void OnDetached() + { + } + + protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) + { + base.OnElementPropertyChanged(args); + try + { + if (args.PropertyName == "IsFocused") + { + if (((Android.Graphics.Drawables.ColorDrawable)Control.Background).Color == backgroundColor) + { + Control.SetBackgroundColor(originalBackgroundColor); + } + else + { + Control.SetBackgroundColor(backgroundColor); + } + } + } + catch (Exception ex) + { + Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); + } + } + } +#elif __IOS__ + public class FocusPlatformEffect : PlatformEffect + { + UIKit.UIColor backgroundColor; + + protected override void OnAttached() + { + try + { + Control.BackgroundColor = backgroundColor = UIKit.UIColor.FromRGB(204, 153, 255); + } + catch (Exception ex) + { + Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); + } + } + + protected override void OnDetached() + { + } + + protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) + { + base.OnElementPropertyChanged(args); + + try + { + if (args.PropertyName == "IsFocused") + { + if (Control.BackgroundColor == backgroundColor) + { + Control.BackgroundColor = UIKit.UIColor.White; + } + else + { + Control.BackgroundColor = backgroundColor; + } + } + } + catch (Exception ex) + { + Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message); + } + } + } +#endif +} \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample/Startup.cs b/src/Controls/samples/Controls.Sample/Startup.cs index 19de29f47875..c7f61cb4dc86 100644 --- a/src/Controls/samples/Controls.Sample/Startup.cs +++ b/src/Controls/samples/Controls.Sample/Startup.cs @@ -51,6 +51,10 @@ public void Configure(IAppHostBuilder appBuilder) // Use a "third party" library that brings in a massive amount of controls appBuilder.UseBordelessEntry(); + appBuilder.ConfigureEffects(builder => + { + builder.Add(); + }); #if DEBUG && !WINDOWS appBuilder.EnableHotReload(); diff --git a/src/Controls/samples/Controls.Sample/ViewModels/CoreViewModel.cs b/src/Controls/samples/Controls.Sample/ViewModels/CoreViewModel.cs index 6395cc2d6ee2..a3dcda5bbb9a 100644 --- a/src/Controls/samples/Controls.Sample/ViewModels/CoreViewModel.cs +++ b/src/Controls/samples/Controls.Sample/ViewModels/CoreViewModel.cs @@ -18,17 +18,20 @@ public class CoreViewModel : BaseGalleryViewModel new SectionModel(typeof(ClipPage), "Clip", "Defines the outline of the contents of an element."), + new SectionModel(typeof(EffectsPage), "Effects", + "Apply Effects to a View."), + new SectionModel(typeof(GesturesPage), "Gestures", "Use tap, pinch, pan, swipe, and drag and drop gestures on View instances."), + new SectionModel(typeof(ModalPage), "Modal", + "Allows you to push and pop Modal Pages."), + new SectionModel(typeof(SemanticsPage), "Semantics", ".NET MAUI allows accessibility values to be set on user interface elements by using Semantics values."), new SectionModel(typeof(TransformationsPage), "Transformations", "Apply scale transformations, rotation, etc. to a View."), - - new SectionModel(typeof(ModalPage), "Modal", - "Allows you to push and pop Modal Pages."), }; } -} \ No newline at end of file +} diff --git a/src/Controls/src/Core/Effect.cs b/src/Controls/src/Core/Effect.cs index 04cbca74e21c..f3bdd0c0b4ed 100644 --- a/src/Controls/src/Core/Effect.cs +++ b/src/Controls/src/Core/Effect.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Platform; namespace Microsoft.Maui.Controls { @@ -10,6 +11,8 @@ internal Effect() { } + internal PlatformEffect PlatformEffect { get; set; } + public Element Element { get; internal set; } public bool IsAttached { get; private set; } @@ -53,6 +56,7 @@ internal virtual void SendAttached() return; OnAttached(); IsAttached = true; + PlatformEffect?.SendAttached(); } internal virtual void SendDetached() @@ -61,6 +65,7 @@ internal virtual void SendDetached() return; OnDetached(); IsAttached = false; + PlatformEffect?.SendDetached(); } internal virtual void SendOnElementPropertyChanged(PropertyChangedEventArgs args) diff --git a/src/Controls/src/Core/Element.cs b/src/Controls/src/Core/Element.cs index d69d9e058306..a86b29e2feb4 100644 --- a/src/Controls/src/Core/Element.cs +++ b/src/Controls/src/Core/Element.cs @@ -506,8 +506,9 @@ void AttachEffect(Effect effect) throw new InvalidOperationException("Cannot attach Effect to multiple sources"); Effect effectToRegister = effect; - if (effect is RoutingEffect) - effectToRegister = ((RoutingEffect)effect).Inner; + if (effect is RoutingEffect re && re.Inner != null) + effectToRegister = re.Inner; + _effectControlProvider.RegisterEffect(effectToRegister); effectToRegister.Element = this; effect.SendAttached(); diff --git a/src/Controls/src/Core/HandlerImpl/Element.Impl.cs b/src/Controls/src/Core/HandlerImpl/Element.Impl.cs index e82626887e60..fd66d95e9451 100644 --- a/src/Controls/src/Core/HandlerImpl/Element.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Element.Impl.cs @@ -1,13 +1,17 @@ using System; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Maui.Controls.Hosting; namespace Microsoft.Maui.Controls { - public partial class Element : Maui.IElement + public partial class Element : Maui.IElement, IEffectControlProvider { IElementHandler _handler; EventHandler _attachedHandler; + EffectsFactory _effectsFactory; Maui.IElement Maui.IElement.Parent => Parent; + EffectsFactory EffectsFactory => _effectsFactory ??= Handler.MauiContext.Services.GetRequiredService(); public IElementHandler Handler { @@ -43,10 +47,20 @@ public IElementHandler Handler protected virtual void OnDetachedHandler() { } - private protected virtual void OnAttachedHandlerCore() => OnAttachedHandler(); + private protected virtual void OnAttachedHandlerCore() + { + OnAttachedHandler(); + AttachNativeEffects(); + } private protected virtual void OnDetachingHandlerCore() => OnDetachingHandler(); + private protected virtual void OnDetachedHandlerCore() + { + OnDetachedHandler(); + DetachNativeEffects(); + } + private protected virtual void OnHandlerSet() { } void SetHandler(IElementHandler newHandler) @@ -84,8 +98,40 @@ void SetHandler(IElementHandler newHandler) if (previousHandler != null) { DetachedHandler?.Invoke(this, EventArgs.Empty); - OnDetachedHandler(); + OnDetachedHandlerCore(); + } + } + + void IEffectControlProvider.RegisterEffect(Effect effect) + { + if (effect is RoutingEffect re && re.Inner != null) + { + re.Element = this; + re.Inner.Element = this; + return; + } + + var platformEffect = EffectsFactory.CreateEffect(effect); + + if (platformEffect != null) + { + platformEffect.Element = this; + effect.PlatformEffect = platformEffect; } + else + { + effect.Element = this; + } + } + + void AttachNativeEffects() + { + EffectControlProvider = this; + } + + void DetachNativeEffects() + { + EffectControlProvider = null; } } } \ No newline at end of file diff --git a/src/Controls/src/Core/AppHostBuilderExtensions.cs b/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs similarity index 97% rename from src/Controls/src/Core/AppHostBuilderExtensions.cs rename to src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs index 411d6b00c8c7..7282699e2026 100644 --- a/src/Controls/src/Core/AppHostBuilderExtensions.cs +++ b/src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.Maui.Controls.Hosting { - public static class AppHostBuilderExtensions + public static partial class AppHostBuilderExtensions { static readonly Dictionary DefaultMauiControlHandlers = new Dictionary { diff --git a/src/Controls/src/Core/Hosting/Effects/AppHostBuilderExtensions.cs b/src/Controls/src/Core/Hosting/Effects/AppHostBuilderExtensions.cs new file mode 100644 index 000000000000..4bb6e931ea2e --- /dev/null +++ b/src/Controls/src/Core/Hosting/Effects/AppHostBuilderExtensions.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Controls.Platform; +using Microsoft.Maui.Hosting; + +namespace Microsoft.Maui.Controls.Hosting +{ + public static partial class AppHostBuilderExtensions + { + public static IAppHostBuilder ConfigureEffects(this IAppHostBuilder builder, Action configureDelegate) + { + builder.ConfigureServices(b => configureDelegate(b)); + return builder; + } + + class EffectCollectionBuilder : IMauiServiceBuilder, IEffectsBuilder + { + internal Dictionary> RegisteredEffects { get; } = new Dictionary>(); + + public void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + services.AddSingleton(); + } + + public void Configure(HostBuilderContext context, IServiceProvider services) + { + var effectsProvider = services.GetRequiredService(); + effectsProvider.SetRegisteredEffects(RegisteredEffects); + } + + public IEffectsBuilder Add() + where TEffect : RoutingEffect + where TPlatformEffect : PlatformEffect, new() + { + RegisteredEffects.Add(typeof(TEffect), () => + { + if (DependencyResolver.Resolve(typeof(TPlatformEffect)) is TPlatformEffect pe) + return pe; + + return new TPlatformEffect(); + }); + return this; + } + + public IEffectsBuilder Add(Type TEffect, Type TPlatformEffect) + { + RegisteredEffects.Add(TEffect, () => + { + return (PlatformEffect)DependencyResolver.ResolveOrCreate(TPlatformEffect); + }); + + return this; + } + } + } + + internal class EffectsFactory + { + Dictionary> _registeredEffects; + + internal void SetRegisteredEffects(Dictionary> registeredEffects) + { + _registeredEffects = registeredEffects; + } + + internal PlatformEffect CreateEffect(Effect fromEffect) + { + if (_registeredEffects.TryGetValue(fromEffect.GetType(), out Func effectType)) + { + return effectType(); + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/Hosting/Effects/IEffectsBuilder.cs b/src/Controls/src/Core/Hosting/Effects/IEffectsBuilder.cs new file mode 100644 index 000000000000..230969fddc7e --- /dev/null +++ b/src/Controls/src/Core/Hosting/Effects/IEffectsBuilder.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Maui.Controls.Platform; + +namespace Microsoft.Maui.Controls.Hosting +{ + public interface IEffectsBuilder + { + IEffectsBuilder Add() + where TEffect : RoutingEffect + where TPlatformEffect : PlatformEffect, new(); + + IEffectsBuilder Add(Type TEffect, Type TPlatformEffect); + } +} diff --git a/src/Controls/src/Core/Platform/PlatformEffect.cs b/src/Controls/src/Core/Platform/PlatformEffect.cs new file mode 100644 index 000000000000..a087edf1c827 --- /dev/null +++ b/src/Controls/src/Core/Platform/PlatformEffect.cs @@ -0,0 +1,29 @@ +using System; +#if __IOS__ || MACCATALYST +using NativeView = UIKit.UIView; +#elif MONOANDROID +using NativeView = Android.Views.View; +#elif WINDOWS +using NativeView = Microsoft.UI.Xaml.FrameworkElement; +#elif NETSTANDARD +using NativeView = System.Object; +#endif + +namespace Microsoft.Maui.Controls.Platform +{ + public abstract class PlatformEffect : PlatformEffect + { + internal override void SendAttached() + { + _ = Element ?? throw new InvalidOperationException("Element cannot be null here"); + Control = (NativeView)Element.Handler.NativeView; + + if (Element.Handler is IViewHandler vh) + Container = (NativeView)(vh.ContainerView ?? vh.NativeView); + else + Container = Control; + + base.SendAttached(); + } + } +} \ No newline at end of file diff --git a/src/Controls/src/Core/PlatformEffect.cs b/src/Controls/src/Core/PlatformEffect.cs index 0c71257394ac..d1f34343951d 100644 --- a/src/Controls/src/Core/PlatformEffect.cs +++ b/src/Controls/src/Core/PlatformEffect.cs @@ -1,19 +1,14 @@ using System.ComponentModel; + namespace Microsoft.Maui.Controls { public abstract class PlatformEffect : Effect where TContainer : class where TControl : class { public TContainer Container { get; internal set; } - [EditorBrowsable(EditorBrowsableState.Never)] - public void SetContainer(TContainer container) => Container = container; - public TControl Control { get; internal set; } - [EditorBrowsable(EditorBrowsableState.Never)] - public void SetControl(TControl control) => Control = control; - protected virtual void OnElementPropertyChanged(PropertyChangedEventArgs args) { } diff --git a/src/Controls/src/Core/Registrar.cs b/src/Controls/src/Core/Registrar.cs index 7e6687f69aee..9b838c7fb8e2 100644 --- a/src/Controls/src/Core/Registrar.cs +++ b/src/Controls/src/Core/Registrar.cs @@ -323,6 +323,28 @@ public static void RegisterStylesheets(InitializationFlags flags) return properties; } + internal static void RegisterEffects(Assembly[] assemblies) + { + foreach (Assembly assembly in assemblies) + { + object[] effectAttributes = assembly.GetCustomAttributesSafe(typeof(ExportEffectAttribute)); + if (effectAttributes == null || effectAttributes.Length == 0) + { + continue; + } + + string resolutionName = assembly.FullName; + var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute)); + if (resolutionNameAttribute != null) + resolutionName = resolutionNameAttribute.ShortName; + + //NOTE: a simple cast to ExportEffectAttribute[] failed on UWP, hence the Array.Copy + var typedEffectAttributes = new ExportEffectAttribute[effectAttributes.Length]; + Array.Copy(effectAttributes, typedEffectAttributes, effectAttributes.Length); + RegisterEffects(resolutionName, typedEffectAttributes); + } + } + public static void RegisterEffects(string resolutionName, ExportEffectAttribute[] effectAttributes) { var exportEffectsLength = effectAttributes.Length; @@ -412,22 +434,6 @@ public static void RegisterAll(Type[] attrTypes, InitializationFlags flags) } } - object[] effectAttributes = assembly.GetCustomAttributesSafe(typeof(ExportEffectAttribute)); - if (effectAttributes == null || effectAttributes.Length == 0) - { - Profile.FrameEnd(frameName); - continue; - } - - string resolutionName = assembly.FullName; - var resolutionNameAttribute = (ResolutionGroupNameAttribute)assembly.GetCustomAttribute(typeof(ResolutionGroupNameAttribute)); - if (resolutionNameAttribute != null) - resolutionName = resolutionNameAttribute.ShortName; - //NOTE: a simple cast to ExportEffectAttribute[] failed on UWP, hence the Array.Copy - var typedEffectAttributes = new ExportEffectAttribute[effectAttributes.Length]; - Array.Copy(effectAttributes, typedEffectAttributes, effectAttributes.Length); - RegisterEffects(resolutionName, typedEffectAttributes); - Profile.FrameEnd(frameName); } diff --git a/src/Controls/src/Core/RoutingEffect.cs b/src/Controls/src/Core/RoutingEffect.cs index 511c78011c7c..cdc7163e89c1 100644 --- a/src/Controls/src/Core/RoutingEffect.cs +++ b/src/Controls/src/Core/RoutingEffect.cs @@ -11,6 +11,10 @@ protected RoutingEffect(string effectId) Inner = Resolve(effectId); } + protected RoutingEffect() + { + } + protected override void OnAttached() { } @@ -22,21 +26,25 @@ protected override void OnDetached() internal override void ClearEffect() { Inner?.ClearEffect(); + PlatformEffect?.ClearEffect(); } internal override void SendAttached() { Inner?.SendAttached(); + PlatformEffect?.SendAttached(); } internal override void SendDetached() { Inner?.SendDetached(); + PlatformEffect?.SendDetached(); } internal override void SendOnElementPropertyChanged(PropertyChangedEventArgs args) { Inner?.SendOnElementPropertyChanged(args); + PlatformEffect?.SendOnElementPropertyChanged(args); } } } \ No newline at end of file