/// <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 }
/// <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)); } }
/// <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)); }
/// <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; }
void IViewManager.OnDropViewInstance(ThemedReactContext reactContext, DependencyObject view) { OnDropViewInstance(reactContext, (TFrameworkElement)view); }
/// <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) { }
/// <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 _); }
/// <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);
/// <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 _); }
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) { }
/// <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) { }
void IViewManager.OnDropViewInstance(ThemedReactContext reactContext, Widget view) { OnDropViewInstance(reactContext, (TView)view); }
public virtual DependencyObject CreateView(ThemedReactContext reactContext, JavaScriptResponderHandler jsResponderHandler) { throw new NotImplementedException(); }