/// <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 }
public void ViewManagersPropertyCache_ViewManager_Set() { var instance = new ViewManagerValueTest(); var setters = ViewManagersPropertyCache.GetNativePropertySettersForViewManagerType(typeof(ViewManagerValueTest)); Assert.AreEqual(3, setters.Count); var props = new ReactStylesDiffMap(new JObject { { "Foo", "v1" }, { "Bar1", "v2" }, { "Bar2", "v3" }, }); AssertEx.Throws<NotSupportedException>(() => setters["Foo"].UpdateShadowNodeProperty(new ShadowNodeValueTest(), props)); AssertEx.Throws<ArgumentNullException>( () => setters["Foo"].UpdateViewManagerProperty(null, null, props), ex => Assert.AreEqual("viewManager", ex.ParamName)); AssertEx.Throws<ArgumentNullException>( () => setters["Foo"].UpdateViewManagerProperty(instance, null, null), ex => Assert.AreEqual("props", ex.ParamName)); setters["Foo"].UpdateViewManagerProperty(instance, null, props); setters["Bar1"].UpdateViewManagerProperty(instance, null, props); setters["Bar2"].UpdateViewManagerProperty(instance, null, props); Assert.AreEqual("v1", instance.FooValue); Assert.AreEqual("v2", instance.BarValues[0]); Assert.AreEqual("v3", instance.BarValues[1]); }
protected override object[] GetViewManagerArgs(DependencyObject view, ReactStylesDiffMap props) { s_args[0] = view; s_args[1] = _index; s_args[2] = ExtractProperty(props); return(s_args); }
private void HandleCreateView(ReactShadowNode cssNode, int rootViewTag, ReactStylesDiffMap styles) { if (!cssNode.IsVirtual) { _nativeViewHierarchyOptimizer.HandleCreateView(cssNode, cssNode.ThemedContext, styles); } }
/// <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> /// Handles the creation of a view. /// </summary> /// <param name="node">The shadow node for the view.</param> /// <param name="rootViewTag">The react tag id of the root.</param> /// <param name="themedContext">The themed context.</param> /// <param name="initialProperties"> /// The initial properties for the view. /// </param> public void HandleCreateView( ReactShadowNode node, int rootViewTag, ThemedReactContext themedContext, ReactStylesDiffMap initialProperties) { #if DISABLE_NATIVE_VIEW_HIERARCHY_OPTIMIZER _uiViewOperationQueue.EnqueueCreateView( themedContext, node.ReactTag, node.ViewClass, initialProperties, rootViewTag); #else var isLayoutOnly = node.ViewClass == ViewProps.ViewClassName && IsLayoutOnlyAndCollapsible(initialProperties); node.IsLayoutOnly = isLayoutOnly; if (!isLayoutOnly) { _uiViewOperationQueue.EnqueueCreateView( themedContext, node.ReactTag, node.ViewClass, initialProperties, rootViewTag); } #endif }
/// <summary> /// Updates the properties of the view with the given tag. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties.</param> public void UpdateProperties(int tag, ReactStylesDiffMap props) { DispatcherHelpers.AssertOnDispatcher(); var viewManager = ResolveViewManager(tag); var viewToUpdate = ResolveView(tag); viewManager.UpdateProperties(viewToUpdate, props); }
public static T GetProperty <T>(this ReactStylesDiffMap props, string name) { var property = props.GetProperty(name, typeof(T)); if (property == null) { throw new Exception("ReactStylesDiffMapExtensions GetProperty error, property is null"); } return((T)property); }
private void HandleUpdateView( ReactShadowNode cssNode, string className, ReactStylesDiffMap styles) { if (!cssNode.IsVirtual) { _nativeViewHierarchyOptimizer.HandleUpdateView(cssNode, className, styles); } }
protected object ExtractProperty(ReactStylesDiffMap props) { if (props.IsNull(Name) && s_defaultValues.TryGetValue(PropertyType, out var defaultFunc)) { return(defaultFunc(_attribute)); } return(props.GetProperty(Name)? .ToObject(PropertyType)); }
private void TransitionLayoutOnlyViewToNativeView(ReactShadowNode node, ReactStylesDiffMap props) { var parent = node.Parent; if (parent == null) { node.IsLayoutOnly = false; return; } // First, remove the node from its parent. This causes the parent // to update its native children count. The call will cause all the // view's children to be detached from their native parent. var childIndex = parent.IndexOf(node); parent.RemoveChildAt(childIndex); RemoveNodeFromParent(node, false); node.IsLayoutOnly = false; // Create the view since it doesn't exist in the native hierarchy yet. _uiViewOperationQueue.EnqueueCreateView( node.RootNode.ThemedContext, node.ReactTag, node.ViewClass, props, node.RootNode.ReactTag); // Add the node and all its children as if adding new nodes. parent.AddChildAt(node, childIndex); AddNodeToNode(parent, node, childIndex); for (var i = 0; i < node.ChildCount; ++i) { AddNodeToNode(node, node.GetChildAt(i), i); } // Update layouts since the children of the node were offset by its // x/y position previously. (Warning: bit of a hack) We need to // update the layout of this node's children now that it's no // longer layout-only, but we may still receive more layout updates // at the end of this batch that we don't want to ignore. // Also <node>.DispatchUpdates optimizes the layout applying out // if screen position/sizes didn't change, yet in this particular case // we want to force the applying of those values since the native view // is a freshly created one with no history. ApplyLayoutBase(node); for (var i = 0; i < node.ChildCount; ++i) { ApplyLayoutBase(node.GetChildAt(i)); } _tagsWithLayoutVisited.Clear(); node.MarkForceLayout(); }
/// <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) { EnqueueOperation(() => _nativeViewHierarchyManager.CreateView( 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> /// <param name="rootViewTag">Root view tag.</param> public void EnqueueCreateView( ThemedReactContext themedContext, int viewReactTag, string viewClassName, ReactStylesDiffMap initialProps, int rootViewTag) { EnqueueCreateView( themedContext, viewReactTag, viewClassName, initialProps); }
public void UpdateShadowNodeProperty(ReactShadowNode shadowNode, ReactStylesDiffMap props) { if (shadowNode == null) { throw new ArgumentNullException(nameof(shadowNode)); } if (props == null) { throw new ArgumentNullException(nameof(props)); } Invoke(shadowNode, GetShadowNodeArgs(props)); }
/// <summary> /// Updates the properties of the node. /// </summary> /// <param name="props">The properties.</param> public void UpdateProperties(ReactStylesDiffMap props) { var setters = ViewManagersPropertyCache.GetNativePropertySettersForShadowNodeType(GetType()); foreach (var key in props.Keys) { if (setters.TryGetValue(key, out var setter)) { setter.UpdateShadowNodeProperty(this, props); } } OnAfterUpdateTransaction(); }
/// <summary> /// Checks if the property key is layout-only. /// </summary> /// <param name="props">The prop collection.</param> /// <param name="prop">The prop name.</param> /// <returns> /// <b>true</b> if the property is layout-only, <b>false</b> otherwise. /// </returns> public static bool IsLayoutOnly(ReactStylesDiffMap props, string prop) { if (s_layoutOnlyProperties.Contains(prop)) { return(true); } else if (PointerEvents == prop) { var value = props.GetProperty(prop).Value <string>(); return(value == "auto" || value == "box-none"); } return(false); }
/// <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> /// 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> /// Handles a call to <see cref="UIManagerModule.updateView(int, string, Newtonsoft.Json.Linq.JObject)"/>. /// If a view transitions from being layout-only to not (or vice versa) /// this could result in some number of additional create view or /// manage children calls. If the view is layout only, no update view /// call will be dispatched to the native hierarchy. /// </summary> /// <param name="node">The node.</param> /// <param name="className">The class name.</param> /// <param name="props">The properties.</param> public void HandleUpdateView(ReactShadowNode node, string className, ReactStylesDiffMap props) { #if DISABLE_NATIVE_VIEW_HIERARCHY_OPTIMIZER _uiViewOperationQueue.EnqueueUpdateProperties(node.ReactTag, className, props); #else var needsToLeaveLayoutOnly = node.IsLayoutOnly && !IsLayoutOnlyAndCollapsible(props); if (needsToLeaveLayoutOnly) { TransitionLayoutOnlyViewToNativeView(node, props); } else if (!node.IsLayoutOnly) { _uiViewOperationQueue.EnqueueUpdateProperties(node.ReactTag, className, props); } #endif }
protected object ExtractProperty(ReactStylesDiffMap props) { if (props.IsNull(Name) && s_defaultValues.TryGetValue(PropertyType, out var defaultFunc)) { return(defaultFunc(_attribute)); } var prop = props.GetProperty(Name)? .ToObject(PropertyType); if (prop == null && PropertyType.GetTypeInfo().IsValueType) { return(Activator.CreateInstance(PropertyType)); } return(prop); }
/// <summary> /// Update the properties of the given view. /// </summary> /// <param name="viewToUpdate">The view to update.</param> /// <param name="props">The properties.</param> public void UpdateProperties(TFrameworkElement viewToUpdate, ReactStylesDiffMap props) { var propertySetters = ViewManagersPropertyCache.GetNativePropertySettersForViewManagerType(GetType()); var keys = props.Keys; foreach (var key in keys) { if (propertySetters.TryGetValue(key, out var setter)) { setter.UpdateViewManagerProperty(this, viewToUpdate, props); } } OnAfterUpdateTransaction(viewToUpdate); }
/// <summary> /// Update the properties of the given view. /// </summary> /// <param name="viewToUpdate">The view to update.</param> /// <param name="props">The properties.</param> public void UpdateProperties(TDependencyObject viewToUpdate, ReactStylesDiffMap props) { var propertySetters = ViewManagersPropertyCache.GetNativePropertySettersForViewManagerType(GetType()); var keys = props.Keys; foreach (var key in keys) { var setter = default(IPropertySetter); if (propertySetters.TryGetValue(key, out setter)) { setter.UpdateViewManagerProperty(this, viewToUpdate, props); } } OnAfterUpdateTransaction(viewToUpdate); }
/// <summary> /// Used by the native animated module to bypass the process of /// updating the values through the shadow view hierarchy. This method /// will directly update the native views, which means that updates for /// layout-related properties won't be handled properly. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties</param> /// <remarks> /// Make sure you know what you're doing before calling this method :) /// </remarks> public bool SynchronouslyUpdateViewOnDispatcherThread(int tag, ReactStylesDiffMap props) { DispatcherHelpers.AssertOnDispatcher(); // First check if the view exists, as the views are created in // batches, and native modules attempting to synchronously interact // with views may attempt to update properties before the batch has // been processed. if (_operationsQueue.NativeViewHierarchyManager.ViewExists(tag)) { _operationsQueue.NativeViewHierarchyManager.UpdateProperties(tag, props); return(true); } else { return(false); } }
/// <summary> /// Invoked by React when the properties change for a node with the /// given tag. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="className">The view class name.</param> /// <param name="props">The properties.</param> public void UpdateView(int tag, string className, JObject props) { var viewManager = _viewManagers.Get(className); var cssNode = _shadowNodeRegistry.GetNode(tag); if (cssNode == null) { throw new InvalidOperationException( $"Trying to update view with invalid tag '{tag}'."); } if (props != null) { var styles = new ReactStylesDiffMap(props); cssNode.UpdateProperties(styles); HandleUpdateView(cssNode, className, styles); } }
/// <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)); }
protected object ExtractProperty(ReactStylesDiffMap props) { var defaultFunc = default(Func <ReactPropBaseAttribute, object>); if (props.IsNull(Name) && s_defaultValues.TryGetValue(PropertyType, out defaultFunc)) { return(defaultFunc(_attribute)); } try { return(props.GetProperty(Name)? .ToObject(PropertyType)); } catch (Exception ex) { Log.Error(ReactConstants.Tag, $"ExtractProperty failed, Name is {Method.Name}, PropertyType is {PropertyType}"); throw ex; } }
/// <summary> /// Used by the native animated module to bypass the process of /// updating the values through the shadow view hierarchy. This method /// will directly update the native views, which means that updates for /// layout-related properties won't be handled properly. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties</param> /// <remarks> /// Make sure you know what you're doing before calling this method :) /// </remarks> public bool SynchronouslyUpdateViewOnDispatcherThread(int tag, ReactStylesDiffMap props) { // The native animations module is a single threaded implementation affinitized to the "main" dispatcher thread. // As a result all calls of this method are on main dispatcher thread. // Yet, for secondary views we have to dispatch to correct dispatcher as fast as possible DispatcherHelpers.AssertOnDispatcher(); UIViewOperationQueueInstance queue = GetQueueByTag(tag, true); if (queue == null) { // Returns false as per the caller's expectation return(false); } if (queue == MainUIViewOperationQueue) { // Main queue case. Just forward. if (!MainUIViewOperationQueue.NativeViewHierarchyManager.ViewExists(tag)) { return(false); } MainUIViewOperationQueue.NativeViewHierarchyManager.UpdateProperties(tag, props); } else { // Dispatch to the correct thread. DispatcherHelpers.RunOnDispatcher(queue.Dispatcher, CoreDispatcherPriority.High, () => { if (queue.NativeViewHierarchyManager.ViewExists(tag)) { queue.NativeViewHierarchyManager.UpdateProperties(tag, props); } else { Debug.WriteLine($"View with tag {tag} not found due to race condition"); } }); } return(true); }
/// <summary> /// Invoked by React to create a new node with the given tag, class /// name, and properties. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="className">The class name.</param> /// <param name="rootViewTag">The root view tag.</param> /// <param name="props">The properties.</param> public void CreateView(int tag, string className, int rootViewTag, JObject props) { var cssNode = CreateShadowNode(className); var rootNode = _shadowNodeRegistry.GetNode(rootViewTag); cssNode.ReactTag = tag; cssNode.ViewClass = className; cssNode.RootNode = rootNode; cssNode.ThemedContext = rootNode.ThemedContext; _shadowNodeRegistry.AddNode(cssNode); var styles = default(ReactStylesDiffMap); if (props != null) { styles = new ReactStylesDiffMap(props); cssNode.UpdateProperties(styles); } HandleCreateView(cssNode, rootViewTag, styles); }
private bool IsLayoutOnlyAndCollapsible(ReactStylesDiffMap props) { if (props == null) { return(true); } if (props.ContainsKey(ViewProps.Collapsible) && !props.GetProperty <bool>(ViewProps.Collapsible)) { return(false); } foreach (var key in props.Keys) { if (!ViewProps.IsLayoutOnly(props, key)) { return(false); } } return(true); }
/// <summary> /// Handles a call to <see cref="UIManagerModule.updateView(int, string, Newtonsoft.Json.Linq.JObject)"/>. /// If a view transitions from being layout-only to not (or vice versa) /// this could result in some number of additional create view or /// manage children calls. If the view is layout only, no update view /// call will be dispatched to the native hierarchy. /// </summary> /// <param name="node">The node.</param> /// <param name="className">The class name.</param> /// <param name="props">The properties.</param> public void HandleUpdateView(ReactShadowNode node, string className, ReactStylesDiffMap props) { #if !ENABLED _uiViewOperationQueue.EnqueueUpdateProperties(node.ReactTag, className, props); #else var needsToLeaveLayoutOnly = node.IsLayoutOnly && !IsLayoutOnlyAndCollapsible(props); if (needsToLeaveLayoutOnly) { TransitionLayoutOnlyViewToNativeView(node, props); } else if (!node.IsLayoutOnly) { _uiViewOperationQueue.EnqueueUpdateProperties(node.ReactTag, className, props); } #endif }
private void TransitionLayoutOnlyViewToNativeView(ReactShadowNode node, ReactStylesDiffMap props) { var parent = node.Parent; if (parent == null) { node.IsLayoutOnly = false; return; } // First, remove the node from its parent. This causes the parent // to update its native children count. The call will cause all the // view's children to be detached from their native parent. var childIndex = parent.IndexOf(node); parent.RemoveChildAt(childIndex); RemoveNodeFromParent(node, false); node.IsLayoutOnly = false; // Create the view since it doesn't exist in the native hierarchy yet. _uiViewOperationQueue.EnqueueCreateView( node.RootNode.ThemedContext, node.ReactTag, node.ViewClass, props); // Add the node and all its children as if adding new nodes. parent.AddChildAt(node, childIndex); AddNodeToNode(parent, node, childIndex); for (var i = 0; i < node.ChildCount; ++i) { AddNodeToNode(node, node.GetChildAt(i), i); } // Update layouts since the children of the node were offset by its // x/y position previously. (Warning: bit of a hack) We need to // update the layout of this node's children now that it's no // longer layout-only, but we may still receive more layout updates // at the end of this batch that we don't want to ignore. ApplyLayoutBase(node); for (var i = 0; i < node.ChildCount; ++i) { ApplyLayoutBase(node.GetChildAt(i)); } _tagsWithLayoutVisited.Clear(); }
private bool IsLayoutOnlyAndCollapsible(ReactStylesDiffMap props) { if (props == null) { return true; } if (props.ContainsKey(ViewProps.Collapsible) && !props.GetProperty<bool>(ViewProps.Collapsible)) { return false; } foreach (var key in props.Keys) { if (!ViewProps.IsLayoutOnly(key)) { return false; } } return true; }
/// <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 (RNTracer.Trace(RNTracer.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 // EvasObject to store the tag of the view. view.SetTag(tag); view.SetReactContext(themedContext); if (initialProperties != null) { viewManager.UpdateProperties(view, initialProperties); } } }
/// <summary> /// Used by the native animated module to bypass the process of /// updating the values through the shadow view hierarchy. This method /// will directly update the native views, which means that updates for /// layout-related properties won't be handled properly. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties</param> /// <remarks> /// Make sure you know what you're doing before calling this method :) /// </remarks> public void SynchronouslyUpdateViewOnDispatcherThread(int tag, ReactStylesDiffMap props) { DispatcherHelpers.AssertOnDispatcher(); _operationsQueue.NativeViewHierarchyManager.UpdateProperties(tag, props); }
private void HandleUpdateView( ReactShadowNode cssNode, string className, ReactStylesDiffMap styles) { if (!cssNode.IsVirtual) { _nativeViewHierarchyOptimizer.HandleUpdateView(cssNode, className, styles); } }
public void ViewManagersPropertyCache_Defaults() { var instance = new DefaultsTest(); var setters = ViewManagersPropertyCache.GetNativePropertySettersForViewManagerType(typeof(DefaultsTest)); var props = new ReactStylesDiffMap(new JObject()); instance.ByteValue = byte.MaxValue; instance.SByteValue = sbyte.MaxValue; instance.Int16Value = short.MaxValue; instance.UInt16Value = ushort.MaxValue; instance.Int32Value = int.MaxValue; instance.UInt32Value = uint.MaxValue; instance.Int64Value = long.MaxValue; instance.UInt64Value = ulong.MaxValue; instance.SingleValue = float.MaxValue; instance.DoubleValue = double.MaxValue; instance.DecimalValue = decimal.MaxValue; instance.BooleanValue = true; instance.StringValue = "foo"; instance.ArrayValue = new int[0]; instance.MapValue = new object(); instance.NullableValue = true; instance.GroupValue = new[] { "a", "b", "c" }; setters["TestByte"].UpdateViewManagerProperty(instance, null, props); setters["TestSByte"].UpdateViewManagerProperty(instance, null, props); setters["TestInt16"].UpdateViewManagerProperty(instance, null, props); setters["TestUInt16"].UpdateViewManagerProperty(instance, null, props); setters["TestInt32"].UpdateViewManagerProperty(instance, null, props); setters["TestUInt32"].UpdateViewManagerProperty(instance, null, props); setters["TestInt64"].UpdateViewManagerProperty(instance, null, props); setters["TestUInt64"].UpdateViewManagerProperty(instance, null, props); setters["TestSingle"].UpdateViewManagerProperty(instance, null, props); setters["TestDouble"].UpdateViewManagerProperty(instance, null, props); setters["TestDecimal"].UpdateViewManagerProperty(instance, null, props); setters["TestBoolean"].UpdateViewManagerProperty(instance, null, props); setters["TestString"].UpdateViewManagerProperty(instance, null, props); setters["TestArray"].UpdateViewManagerProperty(instance, null, props); setters["TestMap"].UpdateViewManagerProperty(instance, null, props); setters["TestNullable"].UpdateViewManagerProperty(instance, null, props); setters["foo"].UpdateViewManagerProperty(instance, null, props); setters["bar"].UpdateViewManagerProperty(instance, null, props); setters["baz"].UpdateViewManagerProperty(instance, null, props); Assert.AreEqual(0, instance.ByteValue); Assert.AreEqual(0, instance.SByteValue); Assert.AreEqual(0, instance.Int16Value); Assert.AreEqual(0, instance.UInt16Value); Assert.AreEqual(0, instance.Int32Value); Assert.AreEqual((uint)0, instance.UInt32Value); Assert.AreEqual(0, instance.Int64Value); Assert.AreEqual((ulong)0, instance.UInt64Value); Assert.AreEqual(0, instance.SingleValue); Assert.AreEqual(0, instance.DoubleValue); Assert.AreEqual(0, instance.DecimalValue); Assert.IsFalse(instance.BooleanValue); Assert.IsNull(instance.StringValue); Assert.IsNull(instance.ArrayValue); Assert.IsNull(instance.MapValue); Assert.IsFalse(instance.NullableValue.HasValue); Assert.IsNull(instance.GroupValue[0]); Assert.IsNull(instance.GroupValue[1]); Assert.IsNull(instance.GroupValue[2]); }
/// <summary> /// Invoked by React to create a new node with the given tag, class /// name, and properties. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="className">The class name.</param> /// <param name="rootViewTag">The root view tag.</param> /// <param name="props">The properties.</param> public void CreateView(int tag, string className, int rootViewTag, JObject props) { var cssNode = CreateShadowNode(className); var rootNode = _shadowNodeRegistry.GetNode(rootViewTag); cssNode.ReactTag = tag; cssNode.ViewClass = className; cssNode.RootNode = rootNode; cssNode.ThemedContext = rootNode.ThemedContext; _shadowNodeRegistry.AddNode(cssNode); var styles = default(ReactStylesDiffMap); if (props != null) { styles = new ReactStylesDiffMap(props); cssNode.UpdateProperties(styles); } HandleCreateView(cssNode, rootViewTag, styles); }
/// <summary> /// Invoked by React when the properties change for a node with the /// given tag. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="className">The view class name.</param> /// <param name="props">The properties.</param> public void UpdateView(int tag, string className, JObject props) { var viewManager = _viewManagers.Get(className); var cssNode = _shadowNodeRegistry.GetNode(tag); if (cssNode == null) { throw new InvalidOperationException( Invariant($"Trying to update view with invalid tag '{tag}'.")); } if (props != null) { var styles = new ReactStylesDiffMap(props); cssNode.UpdateProperties(styles); HandleUpdateView(cssNode, className, styles); } }
/// <summary> /// Used by the native animated module to bypass the process of /// updating the values through the shadow view hierarchy. This method /// will directly update the native views, which means that updates for /// layout-related properties won't be handled properly. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties</param> /// <remarks> /// Make sure you know what you're doing before calling this method :) /// </remarks> public void SynchronouslyUpdateViewOnDispatcherThread(int tag, ReactStylesDiffMap props) { DispatcherHelpers.AssertOnDispatcher(); _operationsQueue.NativeViewHierarchyManager.UpdateProperties(tag, props); }
/// <summary> /// Updates the properties of the view with the given tag. /// </summary> /// <param name="tag">The view tag.</param> /// <param name="props">The properties.</param> public void UpdateProperties(int tag, ReactStylesDiffMap props) { DispatcherHelpers.AssertOnDispatcher(); var viewManager = ResolveViewManager(tag); var viewToUpdate = ResolveView(tag); viewManager.UpdateProperties(viewToUpdate, props); }
/// <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); } } }
public virtual void UpdateProperties(DependencyObject viewToUpdate, ReactStylesDiffMap props) { throw new NotImplementedException(); }
void IViewManager.UpdateProperties(Widget viewToUpdate, ReactStylesDiffMap props) { UpdateProperties((TView)viewToUpdate, props); }
private void HandleCreateView(ReactShadowNode cssNode, int rootViewTag, ReactStylesDiffMap styles) { if (!cssNode.IsVirtual) { _nativeViewHierarchyOptimizer.HandleCreateView(cssNode, cssNode.ThemedContext, styles); } }