/// <summary>
        /// Handles the creation of a view.
        /// </summary>
        /// <param name="node">The shadow node for the view.</param>
        /// <param name="themedContext">The themed context.</param>
        /// <param name="initialProperties">
        /// The initial properties for the view.
        /// </param>
        public void HandleCreateView(
            ReactShadowNode node,
            ThemedReactContext themedContext, 
            ReactStylesDiffMap initialProperties)
        {
#if !ENABLED
            _uiViewOperationQueue.EnqueueCreateView(
                    themedContext,
                    node.ReactTag,
                    node.ViewClass,
                    initialProperties);
#else
            var isLayoutOnly = node.ViewClass == ViewProps.ViewClassName
                && IsLayoutOnlyAndCollapsible(initialProperties);

            node.IsLayoutOnly = isLayoutOnly;

            if (!isLayoutOnly)
            {
                _uiViewOperationQueue.EnqueueCreateView(
                    themedContext,
                    node.ReactTag,
                    node.ViewClass,
                    initialProperties);
            }
#endif
        }
Esempio n. 2
0
        /// <summary>
        /// Enqueues an operation to create a view.
        /// </summary>
        /// <param name="themedContext">The React context.</param>
        /// <param name="viewReactTag">The view React tag.</param>
        /// <param name="viewClassName">The view class name.</param>
        /// <param name="initialProps">The initial properties.</param>
        /// <param name="rootViewTag">Root view tag.</param>
        public void EnqueueCreateView(
            ThemedReactContext themedContext,
            int viewReactTag,
            string viewClassName,
            ReactStylesDiffMap initialProps,
            int rootViewTag)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(rootViewTag);

            _reactTagToOperationQueue.Add(viewReactTag, queue);

            queue.EnqueueCreateView(themedContext, viewReactTag, viewClassName, initialProps);
        }
 /// <summary>
 /// Enqueues an operation to create a view.
 /// </summary>
 /// <param name="themedContext">The React context.</param>
 /// <param name="viewReactTag">The view React tag.</param>
 /// <param name="viewClassName">The view class name.</param>
 /// <param name="initialProps">The initial properties.</param>
 public void EnqueueCreateView(
     ThemedReactContext themedContext,
     int viewReactTag,
     string viewClassName,
     ReactStylesDiffMap initialProps)
 {
     lock (_nonBatchedGate)
     {
         _nonBatchedOperations.Add(() => _nativeViewHierarchyManager.CreateView(
                                       themedContext,
                                       viewReactTag,
                                       viewClassName,
                                       initialProps));
     }
 }
Esempio n. 4
0
        /// <summary>
        /// Registers a new root view.
        /// </summary>
        /// <param name="rootView">The root view instance.</param>
        /// <returns>The root view tag.</returns>
        /// <remarks>
        /// JavaScript can use the returned tag with to add or remove children
        /// to this view through <see cref="manageChildren(int, int[], int[], int[], int[], int[])"/>.
        /// </remarks>
        public int AddMeasuredRootView(ReactRootView rootView)
        {
            // Called on main dispatcher thread
            DispatcherHelpers.AssertOnDispatcher();

            var tag = _nextRootTag;

            _nextRootTag += RootViewTagIncrement;

            var context = new ThemedReactContext(Context);

            DispatcherHelpers.RunOnDispatcher(rootView.Dispatcher, () =>
            {
                var width  = rootView.ActualWidth;
                var height = rootView.ActualHeight;

                _layoutActionQueue.Dispatch(() =>
                {
                    _uiImplementation.RegisterRootView(rootView, tag, width, height, context);
                });

                var resizeCount = 0;

                rootView.SetOnSizeChangedListener((sender, args) =>
                {
                    var currentCount = ++resizeCount;
                    var newWidth     = args.NewSize.Width;
                    var newHeight    = args.NewSize.Height;

                    _layoutActionQueue.Dispatch(() =>
                    {
                        if (currentCount == resizeCount)
                        {
                            _layoutActionQueue.AssertOnThread();
                            _uiImplementation.UpdateRootNodeSize(tag, newWidth, newHeight);
                        }
                    });
                });

#if WINDOWS_UWP
                // Register view in DeviceInfoModule for tracking its dimensions
                Context.GetNativeModule <DeviceInfoModule>().RegisterRootView(rootView, tag);
#endif
            }, true); // Allow inlining

            return(tag);
        }
        /// <summary>
        /// Register the root view.
        /// </summary>
        /// <param name="rootView">The root view.</param>
        /// <param name="tag">The view tag.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="context">The context.</param>
        public void RegisterRootView(
            SizeMonitoringCanvas rootView,
            int tag,
            double width,
            double height,
            ThemedReactContext context)
        {
            var rootCssNode = CreateRootShadowNode();
            rootCssNode.ReactTag = tag;
            rootCssNode.ThemedContext = context;
            rootCssNode.Width = (float)width;
            rootCssNode.Height = (float)height;
            _shadowNodeRegistry.AddRootNode(rootCssNode);

            // Register it with the NativeViewHierarchyManager.
            _operationsQueue.AddRootView(tag, rootView, context);
        }
        /// <summary>
        /// Creates a new view instance of type <see cref="Border"/>.
        /// </summary>
        /// <param name="reactContext">The React context.</param>
        /// <returns>The view instance.</returns>
        protected override Border CreateViewInstance(ThemedReactContext reactContext)
        {
            var inner = CreateInnerElement(reactContext);

#if !WINDOWS_UWP
            return(new UIAutomationBorder
            {
                BorderBrush = s_defaultBorderBrush,
                Child = inner
            });
#else
            return(new Border
            {
                BorderBrush = s_defaultBorderBrush,
                Child = inner
            });
#endif
        }
        /// <summary>
        /// Register the root view.
        /// </summary>
        /// <param name="rootView">The root view.</param>
        /// <param name="tag">The view tag.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="context">The context.</param>
        public void RegisterRootView(
            SizeMonitoringCanvas rootView,
            int tag,
            double width,
            double height,
            ThemedReactContext context)
        {
            var rootCssNode = CreateRootShadowNode();

            rootCssNode.ReactTag      = tag;
            rootCssNode.ThemedContext = context;
            rootCssNode.StyleWidth    = (float)width;
            rootCssNode.StyleHeight   = (float)height;
            _shadowNodeRegistry.AddRootNode(rootCssNode);

            // Register it with the NativeViewHierarchyManager.
            _operationsQueue.AddRootView(tag, rootView, context);
        }
        /// <summary>
        /// Enqueues an operation to create a view.
        /// </summary>
        /// <param name="themedContext">The React context.</param>
        /// <param name="viewReactTag">The view React tag.</param>
        /// <param name="viewClassName">The view class name.</param>
        /// <param name="initialProps">The initial properties.</param>
        public void EnqueueCreateView(
            ThemedReactContext themedContext,
            int viewReactTag,
            string viewClassName,
            ReactStylesDiffMap initialProps)
        {
            lock (_nonBatchedGate)
            {
                _nonBatchedOperations.Add(() => _nativeViewHierarchyManager.CreateView(
                                              themedContext,
                                              viewReactTag,
                                              viewClassName,
                                              initialProps));
            }

            // Dispatch event from non-layout thread to avoid queueing
            // main dispatcher callbacks from the layout thread
            Task.Run(() => ReactChoreographer.Instance.ActivateCallback(NonBatchedChoreographerKey));
        }
Esempio n. 9
0
        /// <summary>
        /// Registers a new root view.
        /// </summary>
        /// <param name="rootView">The root view instance.</param>
        /// <returns>The root view tag.</returns>
        /// <remarks>
        /// JavaScript can use the returned tag with to add or remove children
        /// to this view through <see cref="manageChildren(int, int[], int[], int[], int[], int[])"/>.
        /// </remarks>
        public int AddMeasuredRootView(SizeMonitoringCanvas rootView)
        {
            var tag = _nextRootTag;

            _nextRootTag += RootViewTagIncrement;

            //var width = rootView.ActualWidth;
            //var height = rootView.ActualHeight;

            var geometry = rootView.Geometry;
            var width    = geometry.Width;
            var height   = geometry.Height;

            RNTracer.Write(Common.ReactConstants.Tag, "RootView : " + width + " * " + height);

            var context = new ThemedReactContext(Context);

            _uiImplementation.RegisterRootView(rootView, tag, width, height, context);

            var resizeCount = 0;

            rootView.SetOnSizeChangedListener((sender, args) =>
            {
                var currentCount = ++resizeCount;

                /*
                 * var newWidth = args.NewSize.Width;
                 * var newHeight = args.NewSize.Height;
                 *
                 * Context.RunOnNativeModulesQueueThread(() =>
                 * {
                 *  if (currentCount == resizeCount)
                 *  {
                 *      Context.AssertOnNativeModulesQueueThread();
                 *      _uiImplementation.UpdateRootNodeSize(tag, newWidth, newHeight, _eventDispatcher);
                 *  }
                 * });
                 */
            });

            return(tag);
        }
        /// <summary>
        /// Creates a view with the given tag and class name.
        /// </summary>
        /// <param name="themedContext">The context.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="className">The class name.</param>
        /// <param name="initialProperties">The properties.</param>
        public void CreateView(ThemedReactContext themedContext, int tag, string className, ReactStylesDiffMap initialProperties)
        {
            DispatcherHelpers.AssertOnDispatcher();
            using (Tracer.Trace(Tracer.TRACE_TAG_REACT_VIEW, "NativeViewHierarcyManager.CreateView")
                   .With("tag", tag)
                   .With("className", className))
            {
                var viewManager = _viewManagers.Get(className);
                var view        = viewManager.CreateView(themedContext, _jsResponderHandler);
                _tagsToViews.Add(tag, view);
                _tagsToViewManagers.Add(tag, viewManager);

                // Uses an extension method and `Tag` property on
                // FrameworkElement to store the tag of the view.
                view.SetTag(tag);
                view.SetReactContext(themedContext);

                if (initialProperties != null)
                {
                    viewManager.UpdateProperties(view, initialProperties);
                }
            }
        }
 public virtual void OnDropViewInstance(ThemedReactContext reactContext, DependencyObject view)
 {
     throw new NotImplementedException();
 }
 Widget IViewManager.CreateView(ThemedReactContext reactContext /*, JavaScriptResponderHandler jsResponderHandler*/)
 {
     return(CreateView(reactContext /*, jsResponderHandler*/));
 }
 /// <summary>
 /// Creates a new view instance of type <typeparamref name="TView"/>.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <returns>The view instance.</returns>
 protected abstract TView CreateViewInstance(ThemedReactContext reactContext);
 /// <summary>
 /// Adds a root view with the given tag.
 /// </summary>
 /// <param name="tag">The tag.</param>
 /// <param name="view">The root view.</param>
 /// <param name="themedContext">The themed context.</param>
 public void AddRootView(int tag, SizeMonitoringCanvas view, ThemedReactContext themedContext)
 {
     AddRootViewParent(tag, view, themedContext);
 }
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/> subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 /// <remarks>
 /// Be sure to call this base class method to register for pointer
 /// entered and pointer exited events.
 /// </remarks>
 public override void OnDropViewInstance(ThemedReactContext reactContext, TFrameworkElement view)
 {
     view.MouseEnter -= OnPointerEntered;
     view.MouseLeave -= OnPointerExited;
 }
Esempio n. 16
0
 void IViewManager.OnDropViewInstance(ThemedReactContext reactContext, DependencyObject view)
 {
     OnDropViewInstance(reactContext, (TFrameworkElement)view);
 }
Esempio n. 17
0
 /// <summary>
 /// Subclasses can override this method to install custom event
 /// emitters on the given view.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view instance.</param>
 /// <remarks>
 /// Consider overriding this method if your view needs to emit events
 /// besides basic touch events to JavaScript (e.g., scroll events).
 /// </remarks>
 protected virtual void AddEventEmitters(ThemedReactContext reactContext, TFrameworkElement view)
 {
 }
Esempio n. 18
0
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/> subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 public virtual void OnDropViewInstance(ThemedReactContext reactContext, TFrameworkElement view)
 {
 }
 private void AddRootViewParent(int tag, FrameworkElement view, ThemedReactContext themedContext)
 {
     DispatcherHelpers.AssertOnDispatcher();
     _tagsToViews.Add(tag, view);
     _tagsToViewManagers.Add(tag, _rootViewManager);
     _rootTags.Add(tag, true);
     view.SetTag(tag);
     view.SetReactContext(themedContext);
 }
        /// <summary>
        /// Registers a new root view.
        /// </summary>
        /// <param name="rootView">The root view instance.</param>
        /// <returns>The root view tag.</returns>
        /// <remarks>
        /// JavaScript can use the returned tag with to add or remove children 
        /// to this view through <see cref="manageChildren(int, int[], int[], int[], int[], int[])"/>.
        /// </remarks>
        public int AddMeasuredRootView(SizeMonitoringCanvas rootView)
        {
            var tag = _nextRootTag;
            _nextRootTag += RootViewTagIncrement;

            var width = rootView.ActualWidth;
            var height = rootView.ActualHeight;

            var context = new ThemedReactContext(Context);
            _uiImplementation.RegisterRootView(rootView, tag, width, height, context);

            var resizeCount = 0;

            rootView.SetOnSizeChangedListener((sender, args) =>
            {
                var currentCount = ++resizeCount;
                var newWidth = args.NewSize.Width;
                var newHeight = args.NewSize.Height;

                Context.RunOnNativeModulesQueueThread(() =>
                {
                    if (currentCount == resizeCount)
                    {
                        Context.AssertOnNativeModulesQueueThread();
                        _uiImplementation.UpdateRootNodeSize(tag, newWidth, newHeight, _eventDispatcher);
                    }
                });
            });

            return tag;
        }
 internal virtual void OnViewInstanceCreated(ThemedReactContext reactContext, TView view)
 {
 }
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/> subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 /// <remarks>
 /// Be sure to call this base class method to register for pointer
 /// entered and pointer exited events.
 /// </remarks>
 public override void OnDropViewInstance(ThemedReactContext reactContext, TFrameworkElement view)
 {
     view.PointerEntered -= OnPointerEntered;
     view.PointerExited  -= OnPointerExited;
     _dimensionBoundProperties.TryRemove(view, out _);
 }
Esempio n. 23
0
 /// <summary>
 /// Creates a new view instance of type <typeparamref name="TFrameworkElement"/>.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <returns>The view instance.</returns>
 protected abstract TFrameworkElement CreateViewInstance(ThemedReactContext reactContext);
Esempio n. 24
0
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/> subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 /// <remarks>
 /// Be sure to call this base class method to register for pointer
 /// entered and pointer exited events.
 /// </remarks>
 public override void OnDropViewInstance(ThemedReactContext reactContext, TFrameworkElement view)
 {
     _dimensionBoundProperties.TryRemove(view, out _);
 }
Esempio n. 25
0
 DependencyObject IViewManager.CreateView(ThemedReactContext reactContext)
 {
     return(CreateView(reactContext));
 }
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/>
 /// subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 /// <remarks>
 /// Derived classes do not need to call this base method.
 /// </remarks>
 public virtual void OnDropViewInstance(ThemedReactContext reactContext, TDependencyObject view)
 {
 }
        /// <summary>
        /// Adds a root view to the hierarchy.
        /// </summary>
        /// <param name="tag">The root view tag.</param>
        /// <param name="rootView">The root view.</param>
        /// <param name="themedRootContext">The React context.</param>
        public void AddRootView(
            int tag,
            SizeMonitoringCanvas rootView,
            ThemedReactContext themedRootContext)
        {
            // This is called on layout manager thread

            // Extract dispatcher
            var rootViewDispatcher = rootView.Dispatcher;

            // _dispatcherToOperationQueueInfo contains a mapping of CoreDispatcher to <UIViewOperationQueueInstance, # of ReactRootView instances>.
            // Operation queue instances are created lazily whenever an "unknown" CoreDispatcher is detected. Each operation queue instance
            // works together with one dedicated NativeViewHierarchyManager and one ReactChoreographer.
            // One operation queue is the "main" one:
            // - is coupled with the CoreApplication.MainView dispatcher
            // - drives animations in ALL views
            if (!_dispatcherToOperationQueueInfo.TryGetValue(rootViewDispatcher, out var queueInfo))
            {
                // Queue instance doesn't exist for this dispatcher, we need to create

                // Find the CoreApplicationView associated to the new CoreDispatcher
                CoreApplicationView foundView = CoreApplication.Views.First(v => v.Dispatcher == rootViewDispatcher);

                // Create new ReactChoreographer for this view/dispatcher. It will only be used for its DispatchUICallback services
                var reactChoreographer = ReactChoreographer.CreateSecondaryInstance(foundView);

                queueInfo = new QueueInstanceInfo()
                {
                    queueInstance = new UIViewOperationQueueInstance(
                        _reactContext,
                        new NativeViewHierarchyManager(_viewManagerRegistry, rootViewDispatcher, OnViewsDropped),
                        reactChoreographer),
                    rootViewCount = 1
                };

                lock (_lock)
                {
                    // Add new tuple to map
                    _dispatcherToOperationQueueInfo.AddOrUpdate(rootViewDispatcher, queueInfo, (k, v) => throw new InvalidOperationException("Duplicate key"));

                    if (_active)
                    {
                        // Simulate an OnResume from the correct dispatcher thread
                        // (OnResume/OnSuspend/OnDestroy have this thread affinity, all other methods do enqueuings in a thread safe manner)
                        // (No inlining here so we don't hold lock during call outs. Not a big deal since inlining
                        // is only useful for main UI thread, and this code is not executed for that one)
                        DispatcherHelpers.RunOnDispatcher(rootViewDispatcher, queueInfo.queueInstance.OnResume);
                    }
                }
            }
            else
            {
                // Queue instance does exist.
                // Increment the count of root views. This is helpful for the case the count reaches 0 so we can cleanup the queue.
                queueInfo.rootViewCount++;
            }

            // Add tag
            _reactTagToOperationQueue.Add(tag, queueInfo.queueInstance);

            // Send forward
            queueInfo.queueInstance.AddRootView(tag, rootView, themedRootContext);
        }
 /// <summary>
 /// Creates a new view instance of type <typeparamref name="TDependencyObject"/>.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <returns>The view instance.</returns>
 protected abstract TDependencyObject CreateViewInstance(ThemedReactContext reactContext);
 /// <summary>
 /// Subclasses can override this method to install custom event
 /// emitters on the given view.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view instance.</param>
 /// <remarks>
 /// Consider overriding this method if your view needs to emit events
 /// besides basic touch events to JavaScript (e.g., scroll events).
 ///
 /// Make sure you call the base implementation to ensure base pointer
 /// event handlers are subscribed.
 /// </remarks>
 protected override void AddEventEmitters(ThemedReactContext reactContext, TFrameworkElement view)
 {
     view.MouseEnter += OnPointerEntered;
     view.MouseLeave += OnPointerExited;
 }
 /// <summary>
 /// Subclasses can override this method to install custom event
 /// emitters on the given view.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view instance.</param>
 /// <remarks>
 /// Consider overriding this method if your view needs to emit events
 /// besides basic touch events to JavaScript (e.g., scroll events).
 /// </remarks>
 protected virtual void AddEventEmitters(ThemedReactContext reactContext, TDependencyObject view)
 {
 }
Esempio n. 31
0
 /// <summary>
 /// Creates a new view instance of type <typeparamref name="TFrameworkElement"/>.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <returns>The view instance.</returns>
 protected abstract TFrameworkElement CreateInnerElement(ThemedReactContext reactContext);
 DependencyObject IViewManager.CreateView(ThemedReactContext reactContext, JavaScriptResponderHandler jsResponderHandler)
 {
     return(CreateView(reactContext, jsResponderHandler));
 }
 /// <summary>
 /// Called when view is detached from view hierarchy and allows for
 /// additional cleanup by the <see cref="IViewManager"/> subclass.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view.</param>
 public virtual void OnDropViewInstance(ThemedReactContext reactContext, TView view)
 {
 }
        /// <summary>
        /// Creates a view with the given tag and class name.
        /// </summary>
        /// <param name="themedContext">The context.</param>
        /// <param name="tag">The tag.</param>
        /// <param name="className">The class name.</param>
        /// <param name="initialProperties">The properties.</param>
        public void CreateView(ThemedReactContext themedContext, int tag, string className, ReactStylesDiffMap initialProperties)
        {
            DispatcherHelpers.AssertOnDispatcher();
            using (Tracer.Trace(Tracer.TRACE_TAG_REACT_VIEW, "NativeViewHierarcyManager.CreateView")
                .With("tag", tag)
                .With("className", className)
                .Start())
            {
                var viewManager = _viewManagers.Get(className);
                var view = viewManager.CreateView(themedContext, _jsResponderHandler);
                _tagsToViews.Add(tag, view);
                _tagsToViewManagers.Add(tag, viewManager);

                // Uses an extension method and `Tag` property on 
                // DependencyObject to store the tag of the view.
                view.SetTag(tag);
                view.SetReactContext(themedContext);

                if (initialProperties != null)
                {
                    viewManager.UpdateProperties(view, initialProperties);
                }
            }
        }
 /// <summary>
 /// Subclasses can override this method to install custom event
 /// emitters on the given view.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="view">The view instance.</param>
 /// <remarks>
 /// Consider overriding this method if your view needs to emit events
 /// besides basic touch events to JavaScript (e.g., scroll events).
 /// </remarks>
 protected virtual void AddEventEmitters(ThemedReactContext reactContext, TView view)
 {
 }
 /// <summary>
 /// Adds a root view with the given tag.
 /// </summary>
 /// <param name="tag">The tag.</param>
 /// <param name="view">The root view.</param>
 /// <param name="themedContext">The themed context.</param>
 public void AddRootView(int tag, SizeMonitoringCanvas view, ThemedReactContext themedContext)
 {
     AddRootViewParent(tag, view, themedContext);
 }
 void IViewManager.OnDropViewInstance(ThemedReactContext reactContext, Widget view)
 {
     OnDropViewInstance(reactContext, (TView)view);
 }
 public virtual DependencyObject CreateView(ThemedReactContext reactContext, JavaScriptResponderHandler jsResponderHandler)
 {
     throw new NotImplementedException();
 }