Example #1
0
        private static void RegisterElementEvents(FrameworkElement element, IAnimationSettings settings, bool useSecondarySettings = false)
        {
            var eventName = settings?.Event ?? nameof(FrameworkElement.Loaded);

            if (eventName.Equals(AnimationSettings.None, StringComparison.OrdinalIgnoreCase))
            {
                // Do nothing for "None"
            }
            else if (eventName.Equals(nameof(FrameworkElement.Visibility), StringComparison.OrdinalIgnoreCase))
            {
                element
                .Observe(FrameworkElement.VisibilityProperty)
                .Where(_ => element.Visibility == Visibility.Visible)
                .TakeUntil(element.Events().Unloaded)
                .Subscribe(
                    _ => PrepareAnimations(element, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger?.LogError($"Error on subscription to the {nameof(FrameworkElement.Visibility)} changes of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );
            }
            else if (eventName.Equals(nameof(FrameworkElement.DataContextChanged), StringComparison.OrdinalIgnoreCase))
            {
                element
                .Events()
                .DataContextChanged
                .DistinctUntilChanged(args => args.EventArgs.NewValue)
                .TakeUntil(element.Events().Unloaded)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger?.LogError($"Error on subscription to the {nameof(FrameworkElement.DataContextChanged)} event.", ex),
                    () => Cleanup(element)
                    );
            }
            else
            {
                Observable.FromEventPattern(element, eventName)
                .TakeUntil(element.Events().Unloaded)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger?.LogError($"Error on subscription to the {eventName} event.", ex),
                    () => Cleanup(element));
            }
        }
        static IObservable<bool> TryFocusImpl(FrameworkElement element, Func<FrameworkElement, bool> focusAction)
        {
            if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
            {
                return Observable.Return(false);
            }

            var elementObs = element.IsLoaded
                ? Observable.Return(element)
                : element.Events().Loaded
                    .FirstAsync()
                    .Timeout(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler)
                    .Select(_ => element);

            return elementObs
                .SelectMany(e =>
                {
                    var focusObs = Observable.Defer(() =>
                    {
                        if (focusAction(element))
                            return Observable.Return(true);

                        return Observable.Throw<bool>(new InvalidOperationException("Could not move focus"));
                    });

                    // MoveFocus almost always requires its descendant elements to be fully loaded, we
                    // have no way of knowing if they are so we'll try a few times before bailing out.
                    return focusObs.RetryWithBackoffStrategy(
                        retryCount: 5,
                        strategy: i => TimeSpan.FromMilliseconds(i * 50),
                        scheduler: RxApp.MainThreadScheduler
                    );
                })
                .Catch(Observable.Return(false))
                .FirstAsync();
        }
Example #3
0
        private static void RegisterElementEvents(FrameworkElement element, IAnimationSettings settings, bool useSecondarySettings = false)
        {
            switch (settings?.Event ?? AnimationSettings.DEFAULT_EVENT)
            {
            case EventType.Loaded:
            {
                element
                .Events()
                .LoadedUntilUnloaded
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Loaded)} event of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.Visibility:
            {
                element
                .Observe(FrameworkElement.VisibilityProperty)
                .Where(_ => element.Visibility == Visibility.Visible)
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    _ => PrepareAnimations(element, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Visibility)} changes of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.DataContextChanged:
            {
                element
                .Events()
                .DataContextChanged
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.DataContextChanged)} event of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.PointerOver:
            {
                element
                .Events()
                .PointerEntered
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
#if __WPF__
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.MouseEnter)} event of {nameof(FrameworkElement)}", ex),
#else
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.PointerEntered)} event of {nameof(FrameworkElement)}", ex),
#endif
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.PointerExit:
            {
                element
                .Events()
                .PointerExited
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
#if __WPF__
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.MouseLeave)} event of {nameof(FrameworkElement)}", ex),
#else
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.PointerExited)} event of {nameof(FrameworkElement)}", ex),
#endif
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.GotFocus:
            {
                element
                .Events()
                .GotFocus
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.GotFocus)} event of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );

                break;
            }

            case EventType.LostFocus:
            {
                element
                .Events()
                .LostFocus
                .TakeUntil(element.Events().UnloadedMaterialized)
                .Subscribe(
                    args => PrepareAnimations(args.Sender as FrameworkElement, useSecondaryAnimation: useSecondarySettings),
                    ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.LostFocus)} event of {nameof(FrameworkElement)}", ex),
                    () => Cleanup(element)
                    );

                break;
            }
            }
        }
Example #4
0
        // This can be called from the three main entry-points (Primary, Secondary, and StartWith)
        private static void InitializeElement(FrameworkElement element)
        {
            if (GetIsInitialized(element))
            {
                return;
            }

            // Set IsInitialized to true to only run this code once per element
            SetIsInitialized(element, true);

#if __UWP__
            // The new way of handling translate animations (see Translation property section):
            // https://blogs.windows.com/buildingapps/2017/06/22/sweet-ui-made-possible-easy-windows-ui-windows-10-creators-update/
            ElementCompositionPreview.SetIsTranslationEnabled(element, true);
#endif

            element
            .Events()
            .LoadedUntilUnloaded
            .Take(1)
            .Subscribe(
                args =>
            {
                // Perform validations on element's attached properties
                Validate(element);

                var startSettings = element.GetSettings(SettingsTarget.StartWith, getStartWithFunc: GetStartWith);

                // If any StartWith settings were specified, apply them
                if (startSettings != null)
                {
                    element.ApplyInitialSettings((AnimationSettings)startSettings);
                }
            },
                ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Loaded)} event of {nameof(FrameworkElement)}", ex)
                );

            element
            .Observe(UIElement.VisibilityProperty)
            .TakeUntil(element.Events().UnloadedMaterialized)
            .Subscribe(
                _ =>
            {
                var isVisible   = element.Visibility == Visibility.Visible;
                var elementGuid = GetElementGuid(element);

                if (isVisible && _actives.GetNextIdleActiveTimeline(elementGuid)?.Timeline is Timeline idle)
                {
                    RunNextAnimation(idle, element);
                }
            },
                ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.Visibility)} changes of {nameof(FrameworkElement)}", ex)
                );

#if __UWP__
            element
            .Events()
            .SizeChanged
            .TakeUntil(element.Events().UnloadedMaterialized)
            .Subscribe(
                args =>
            {
                // If the element child is a SpriteVisual, maintain its size so update any effects applied
                if (args.Sender is FrameworkElement elem &&
                    ElementCompositionPreview.GetElementChildVisual(elem) is SpriteVisual sprite)
                {
                    sprite.Size = new Vector2((float)elem.ActualWidth, (float)elem.ActualHeight);
                }
            },
                ex => Logger.ErrorException($"Error on subscription to the {nameof(FrameworkElement.SizeChanged)} event of {nameof(FrameworkElement)}", ex)
                );
#endif
        }