[NUI] Revert "Sync with dalihub & API5 branch (#631)" (#635)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / XamlBinding / Element.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.Collections.Specialized;
5 using System.ComponentModel;
6 using System.Runtime.CompilerServices;
7 using System.Xml;
8 using Tizen.NUI.Binding.Internals;
9
10 namespace Tizen.NUI.Binding
11 {
12     /// <summary>
13     /// Provides the base class for all Tizen.NUI.Binding hierarchal elements. This class contains all the methods and properties required to represent an element in the Tizen.NUI.Binding hierarchy.
14     /// </summary>
15     [EditorBrowsable(EditorBrowsableState.Never)]
16     public abstract partial class Element : BindableObject, IElement, INameScope, IElementController
17     {
18
19         // public static readonly BindableProperty MenuProperty = BindableProperty.CreateAttached(nameof(Menu), typeof(Menu), typeof(Element), null);
20
21         // public static Menu GetMenu(BindableObject bindable)
22         // {
23         //   return (Menu)bindable.GetValue(MenuProperty);
24         // }
25
26         // public static void SetMenu(BindableObject bindable, Menu menu)
27         // {
28         //   bindable.SetValue(MenuProperty, menu);
29         // }
30
31         internal static readonly ReadOnlyCollection<Element> EmptyChildren = new ReadOnlyCollection<Element>(new Element[0]);
32
33         /// <summary>
34         /// Identifies the ClassId bindable property.
35         /// </summary>
36         internal static readonly BindableProperty ClassIdProperty = BindableProperty.Create("ClassId", typeof(string), typeof(Tizen.NUI.BaseComponents.View), null);
37
38         string _automationId;
39
40         IList<BindableObject> _bindableResources;
41
42         List<Action<object, ResourcesChangedEventArgs>> _changeHandlers;
43
44         Dictionary<BindableProperty, string> _dynamicResources;
45
46         IEffectControlProvider _effectControlProvider;
47
48         TrackableCollection<Effect> _effects;
49
50         Guid? _id;
51
52         Element _parentOverride;
53
54         IPlatform _platform;
55
56         string _styleId;
57
58         /// <summary>
59         /// Gets or sets a value that allows the automation framework to find and interact with this element.
60         /// </summary>
61         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
62         [EditorBrowsable(EditorBrowsableState.Never)]
63         public string AutomationId
64         {
65             get { return _automationId; }
66             set
67             {
68                 if (_automationId != null)
69                     throw new InvalidOperationException("AutomationId may only be set one time");
70                 _automationId = value;
71             }
72         }
73
74         /// <summary>
75         /// Gets or sets a value used to identify a collection of semantically similar elements.
76         /// </summary>
77         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
78         [EditorBrowsable(EditorBrowsableState.Never)]
79         public string ClassId
80         {
81             get { return (string)GetValue(ClassIdProperty); }
82             set { SetValue(ClassIdProperty, value); }
83         }
84
85         internal IList<Effect> Effects
86         {
87             get
88             {
89                 if (_effects == null)
90                 {
91                     _effects = new TrackableCollection<Effect>();
92                     _effects.CollectionChanged += EffectsOnCollectionChanged;
93                     _effects.Clearing += EffectsOnClearing;
94                 }
95                 return _effects;
96             }
97         }
98
99         /// <summary>
100         /// Gets a value that can be used to uniquely identify an element through the run of an application.
101         /// </summary>
102         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
103         [EditorBrowsable(EditorBrowsableState.Never)]
104         public Guid Id
105         {
106             get
107             {
108                 if (!_id.HasValue)
109                     _id = Guid.NewGuid();
110                 return _id.Value;
111             }
112         }
113
114         /// <summary>
115         /// Gets the element which is the closest ancestor of this element that is a BaseHandle.
116         /// </summary>
117         [Obsolete("ParentView is obsolete as of version 2.1.0. Please use Parent instead.")]
118         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
119         [EditorBrowsable(EditorBrowsableState.Never)]
120         public /*VisualElement*/BaseHandle ParentView
121         {
122             get
123             {
124                 Element parent = Parent;
125                 while (parent != null)
126                 {
127                     var parentView = parent as /*VisualElement*/BaseHandle;
128                     if (parentView != null)
129                         return parentView;
130                     parent = parent.RealParent;
131                 }
132                 return null;
133             }
134         }
135
136         /// <summary>
137         /// Gets or sets a user defined value to uniquely identify the element.
138         /// </summary>
139         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
140         [EditorBrowsable(EditorBrowsableState.Never)]
141         public string StyleId
142         {
143             get { return _styleId; }
144             set
145             {
146                 if (_styleId == value)
147                     return;
148
149                 OnPropertyChanging();
150                 _styleId = value;
151                 OnPropertyChanged();
152             }
153         }
154
155         internal virtual ReadOnlyCollection<Element> LogicalChildrenInternal => EmptyChildren;
156
157         /// <summary>
158         /// For internal use.
159         /// </summary>
160         [EditorBrowsable(EditorBrowsableState.Never)]
161         public ReadOnlyCollection<Element> LogicalChildren => LogicalChildrenInternal;
162
163         internal bool Owned { get; set; }
164
165         internal Element ParentOverride
166         {
167             get { return _parentOverride; }
168             set
169             {
170                 if (_parentOverride == value)
171                     return;
172
173                 bool emitChange = Parent != value;
174
175                 if (emitChange)
176                     OnPropertyChanging(nameof(Parent));
177
178                 _parentOverride = value;
179
180                 if (emitChange)
181                     OnPropertyChanged(nameof(Parent));
182             }
183         }
184
185         /// <summary>
186         /// For internal use.
187         /// </summary>
188         internal IPlatform Platform
189         {
190             get
191             {
192                 if (_platform == null && RealParent != null)
193                     return RealParent.Platform;
194                 return _platform;
195             }
196             set
197             {
198                 if (_platform == value)
199                     return;
200                 _platform = value;
201                 PlatformSet?.Invoke(this, EventArgs.Empty);
202                 foreach (Element descendant in Descendants())
203                 {
204                     descendant._platform = _platform;
205                     descendant.PlatformSet?.Invoke(this, EventArgs.Empty);
206                 }
207             }
208         }
209
210         /// <summary>
211         /// For internal use.
212         /// </summary>
213         [EditorBrowsable(EditorBrowsableState.Never)]
214         public Element RealParent { get; private set; }
215
216         Dictionary<BindableProperty, string> DynamicResources
217         {
218             get { return _dynamicResources ?? (_dynamicResources = new Dictionary<BindableProperty, string>()); }
219         }
220
221         void IElement.AddResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
222         {
223             _changeHandlers = _changeHandlers ?? new List<Action<object, ResourcesChangedEventArgs>>(2);
224             _changeHandlers.Add(onchanged);
225         }
226
227         /// <summary>
228         /// Gets or sets the parent element of the element.
229         /// </summary>
230         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
231         [EditorBrowsable(EditorBrowsableState.Never)]
232         public Element Parent
233         {
234             get { return _parentOverride ?? RealParent; }
235             set
236             {
237                 if (RealParent == value)
238                     return;
239
240                 OnPropertyChanging();
241
242                 if (RealParent != null)
243                     ((IElement)RealParent).RemoveResourcesChangedListener(OnParentResourcesChanged);
244                 RealParent = value;
245                 if (RealParent != null)
246                 {
247                     OnParentResourcesChanged(RealParent?.GetMergedResources());
248                     ((IElement)RealParent).AddResourcesChangedListener(OnParentResourcesChanged);
249                 }
250
251                 object context = value != null ? value.BindingContext : null;
252                 if (value != null)
253                 {
254                     value.SetChildInheritedBindingContext(this, context);
255                 }
256                 else
257                 {
258                     SetInheritedBindingContext(this, null);
259                 }
260
261                 OnParentSet();
262
263                 if (RealParent != null)
264                 {
265                     IPlatform platform = RealParent.Platform;
266                     if (platform != null)
267                         Platform = platform;
268                 }
269
270                 OnPropertyChanged();
271             }
272         }
273
274         void IElement.RemoveResourcesChangedListener(Action<object, ResourcesChangedEventArgs> onchanged)
275         {
276             if (_changeHandlers == null)
277                 return;
278             _changeHandlers.Remove(onchanged);
279         }
280
281         /// <summary>
282         /// For internal use.
283         /// </summary>
284         internal IEffectControlProvider EffectControlProvider
285         {
286             get { return _effectControlProvider; }
287             set
288             {
289                 if (_effectControlProvider == value)
290                     return;
291                 if (_effectControlProvider != null && _effects != null)
292                 {
293                     foreach (Effect effect in _effects)
294                         effect?.SendDetached();
295                 }
296                 _effectControlProvider = value;
297                 if (_effectControlProvider != null && _effects != null)
298                 {
299                     foreach (Effect effect in _effects)
300                     {
301                         if (effect != null)
302                             AttachEffect(effect);
303                     }
304                 }
305             }
306         }
307
308         //void IElementController.SetValueFromRenderer(BindableProperty property, object value) => SetValueFromRenderer(property, value);
309
310         /// <summary>
311         /// Sets the value of the specified property.
312         /// </summary>
313         /// <param name="property">The BindableProperty on which to assign a value.</param>
314         /// <param name="value">The value to set.</param>
315         internal void SetValueFromRenderer(BindableProperty property, object value)
316         {
317             SetValueCore(property, value);
318         }
319
320         /// <summary>
321         /// Sets the value of the propertyKey.
322         /// </summary>
323         /// <param name="property">The BindablePropertyKey on which to assign a value.</param>
324         /// <param name="value">The value to set.</param>
325         internal void SetValueFromRenderer(BindablePropertyKey property, object value)
326         {
327             SetValueCore(property, value);
328         }
329
330         /// <summary>
331         /// For internal use.
332         /// </summary>
333         /// <param name="name">The nameof the effect</param>
334         /// <returns>true if attached</returns>
335         [EditorBrowsable(EditorBrowsableState.Never)]
336         public bool EffectIsAttached(string name)
337         {
338             foreach (var effect in Effects)
339             {
340                 if (effect.ResolveId == name)
341                     return true;
342             }
343             return false;
344         }
345
346         object INameScope.FindByName(string name)
347         {
348             INameScope namescope = GetNameScope();
349             if (namescope == null)
350                 throw new InvalidOperationException("this element is not in a namescope");
351             return namescope.FindByName(name);
352         }
353
354         void INameScope.RegisterName(string name, object scopedElement)
355         {
356             INameScope namescope = GetNameScope();
357             if (namescope == null)
358                 throw new InvalidOperationException("this element is not in a namescope");
359             namescope.RegisterName(name, scopedElement);
360         }
361
362         [Obsolete]
363         void INameScope.RegisterName(string name, object scopedElement, IXmlLineInfo xmlLineInfo)
364         {
365             INameScope namescope = GetNameScope();
366             if (namescope == null)
367                 throw new InvalidOperationException("this element is not in a namescope");
368             namescope.RegisterName(name, scopedElement, xmlLineInfo);
369         }
370
371         void INameScope.UnregisterName(string name)
372         {
373             INameScope namescope = GetNameScope();
374             if (namescope == null)
375                 throw new InvalidOperationException("this element is not in a namescope");
376             namescope.UnregisterName(name);
377         }
378
379         internal event EventHandler<ElementEventArgs> ChildAdded;
380
381         internal event EventHandler<ElementEventArgs> ChildRemoved;
382
383         internal event EventHandler<ElementEventArgs> DescendantAdded;
384
385         internal event EventHandler<ElementEventArgs> DescendantRemoved;
386
387         /// <summary>
388         /// Removes a previously set dynamic resource.
389         /// </summary>
390         /// <param name="property">The BindableProperty from which to remove the DynamicResource.</param>
391         internal new void RemoveDynamicResource(BindableProperty property)
392         {
393             base.RemoveDynamicResource(property);
394         }
395
396         /// <summary>
397         /// Sets the BindableProperty property of this element to be updated via the DynamicResource with the provided key.
398         /// </summary>
399         /// <param name="property">The BindableProperty.</param>
400         /// <param name="key">The key of the DynamicResource</param>
401         internal new void SetDynamicResource(BindableProperty property, string key)
402         {
403             base.SetDynamicResource(property, key);
404         }
405
406         /// <summary>
407         /// Invoked whenever the binding context of the element changes. Implement this method to add class handling for this event.
408         /// </summary>
409         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
410         [EditorBrowsable(EditorBrowsableState.Never)]
411         protected override void OnBindingContextChanged()
412         {
413             var gotBindingContext = false;
414             object bc = null;
415
416             for (var index = 0; index < LogicalChildrenInternal.Count; index++)
417             {
418                 Element child = LogicalChildrenInternal[index];
419
420                 if (!gotBindingContext)
421                 {
422                     bc = BindingContext;
423                     gotBindingContext = true;
424                 }
425
426                 SetChildInheritedBindingContext(child, bc);
427             }
428
429             if (_bindableResources != null)
430                 foreach (BindableObject item in _bindableResources)
431                 {
432                     SetInheritedBindingContext(item, BindingContext);
433                 }
434
435             base.OnBindingContextChanged();
436         }
437
438         /// <summary>
439         /// Invoked whenever the ChildAdded event needs to be emitted.Implement this method to add class handling for this event.
440         /// </summary>
441         /// <param name="child">The element that was added.</param>
442         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
443         [EditorBrowsable(EditorBrowsableState.Never)]
444         protected virtual void OnChildAdded(Element child)
445         {
446             child.Parent = this;
447             if (Platform != null)
448                 child.Platform = Platform;
449
450             child.ApplyBindings(skipBindingContext: false, fromBindingContextChanged:true);
451
452             ChildAdded?.Invoke(this, new ElementEventArgs(child));
453
454             OnDescendantAdded(child);
455             foreach (Element element in child.Descendants())
456                 OnDescendantAdded(element);
457         }
458
459         /// <summary>
460         /// Invoked whenever the ChildRemoved event needs to be emitted.Implement this method to add class handling for this event.
461         /// </summary>
462         /// <param name="child">The element that was removed.</param>
463         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
464         [EditorBrowsable(EditorBrowsableState.Never)]
465         protected virtual void OnChildRemoved(Element child)
466         {
467             child.Parent = null;
468
469             ChildRemoved?.Invoke(child, new ElementEventArgs(child));
470
471             OnDescendantRemoved(child);
472             foreach (Element element in child.Descendants())
473                 OnDescendantRemoved(element);
474         }
475
476         /// <summary>
477         /// Invoked whenever the Parent of an element is set.Implement this method in order to add behavior when the element is added to a parent.
478         /// </summary>
479         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
480         [EditorBrowsable(EditorBrowsableState.Never)]
481         protected virtual void OnParentSet()
482         {
483             ParentSet?.Invoke(this, EventArgs.Empty);
484             // ApplyStyleSheetsOnParentSet();
485         }
486
487         /// <summary>
488         /// Method that is called when a bound property is changed.
489         /// </summary>
490         /// <param name="propertyName">The name of the bound property that changed.</param>
491         /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
492         [EditorBrowsable(EditorBrowsableState.Never)]
493         protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
494         {
495             base.OnPropertyChanged(propertyName);
496
497             if (_effects == null || _effects.Count == 0)
498                 return;
499
500             var args = new PropertyChangedEventArgs(propertyName);
501             foreach (Effect effect in _effects)
502             {
503                 effect?.SendOnElementPropertyChanged(args);
504             }
505         }
506
507         /// <summary>
508         /// For internal use.
509         /// </summary>
510         /// <returns>the elements</returns>
511         [EditorBrowsable(EditorBrowsableState.Never)]
512         public IEnumerable<Element> Descendants()
513         {
514             var queue = new Queue<Element>(16);
515             queue.Enqueue(this);
516
517             while (queue.Count > 0)
518             {
519                 ReadOnlyCollection<Element> children = queue.Dequeue().LogicalChildrenInternal;
520                 for (var i = 0; i < children.Count; i++)
521                 {
522                     Element child = children[i];
523                     yield return child;
524                     queue.Enqueue(child);
525                 }
526             }
527         }
528
529         internal virtual void OnParentResourcesChanged(object sender, ResourcesChangedEventArgs e)
530         {
531             // if (e == ResourcesChangedEventArgs.StyleSheets)
532             //  // ApplyStyleSheetsOnParentSet();
533             // else
534             //  OnParentResourcesChanged(e.Values);
535         }
536
537         internal virtual void OnParentResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
538         {
539             OnResourcesChanged(values);
540         }
541
542         internal override void OnRemoveDynamicResource(BindableProperty property)
543         {
544             DynamicResources.Remove(property);
545
546             if (DynamicResources.Count == 0)
547                 _dynamicResources = null;
548             base.OnRemoveDynamicResource(property);
549         }
550
551         internal virtual void OnResourcesChanged(object sender, ResourcesChangedEventArgs e)
552         {
553             OnResourcesChanged(e.Values);
554         }
555
556         internal void OnResourcesChanged(IEnumerable<KeyValuePair<string, object>> values)
557         {
558             if (values == null)
559                 return;
560             if (_changeHandlers != null)
561                 foreach (Action<object, ResourcesChangedEventArgs> handler in _changeHandlers)
562                     handler(this, new ResourcesChangedEventArgs(values));
563             if (_dynamicResources == null)
564                 return;
565             if (_bindableResources == null)
566                 _bindableResources = new List<BindableObject>();
567             foreach (KeyValuePair<string, object> value in values)
568             {
569                 List<BindableProperty> changedResources = null;
570                 foreach (KeyValuePair<BindableProperty, string> dynR in DynamicResources)
571                 {
572                     // when the DynamicResource bound to a BindableProperty is
573                     // changing then the BindableProperty needs to be refreshed;
574                     // The .Value is the name of DynamicResouce to which the BindableProperty is bound.
575                     // The .Key is the name of the DynamicResource whose value is changing.
576                     if (dynR.Value != value.Key)
577                         continue;
578                     changedResources = changedResources ?? new List<BindableProperty>();
579                     changedResources.Add(dynR.Key);
580                 }
581                 if (changedResources == null)
582                     continue;
583                 foreach (BindableProperty changedResource in changedResources)
584                     OnResourceChanged(changedResource, value.Value);
585
586                 var bindableObject = value.Value as BindableObject;
587                 if (bindableObject != null && (bindableObject as Element)?.Parent == null)
588                 {
589                     if (!_bindableResources.Contains(bindableObject))
590                         _bindableResources.Add(bindableObject);
591                     SetInheritedBindingContext(bindableObject, BindingContext);
592                 }
593             }
594         }
595
596         internal override void OnSetDynamicResource(BindableProperty property, string key)
597         {
598             base.OnSetDynamicResource(property, key);
599             DynamicResources[property] = key;
600             object value;
601             if (this.TryGetResource(key, out value))
602                 OnResourceChanged(property, value);
603         }
604
605         internal event EventHandler ParentSet;
606
607         internal static void SetFlowDirectionFromParent(Element child)
608         {
609             // IFlowDirectionController controller = child as IFlowDirectionController;
610             // if (controller == null)
611             //  return;
612
613             // if (controller.EffectiveFlowDirection.IsImplicit())
614             // {
615             //  var parentView = child.Parent as IFlowDirectionController;
616             //  if (parentView == null)
617             //          return;
618
619             //  var flowDirection = parentView.EffectiveFlowDirection.ToFlowDirection();
620
621             //  if (flowDirection != controller.EffectiveFlowDirection.ToFlowDirection())
622             //  {
623             //          controller.EffectiveFlowDirection = flowDirection.ToEffectiveFlowDirection();
624             //  }
625             // }
626         }
627
628         /// <summary>
629         /// For internal use.
630         /// </summary>
631         [EditorBrowsable(EditorBrowsableState.Never)]
632         public event EventHandler PlatformSet;
633
634         internal virtual void SetChildInheritedBindingContext(Element child, object context)
635         {
636             SetInheritedBindingContext(child, context);
637         }
638
639         internal IEnumerable<Element> VisibleDescendants()
640         {
641             var queue = new Queue<Element>(16);
642             queue.Enqueue(this);
643
644             while (queue.Count > 0)
645             {
646                 ReadOnlyCollection<Element> children = queue.Dequeue().LogicalChildrenInternal;
647                 for (var i = 0; i < children.Count; i++)
648                 {
649                     var child = children[i] as /*VisualElement*/BaseHandle;
650                     if (child == null /*|| !child.IsVisible*/)
651                         continue;
652                     yield return child;
653                     queue.Enqueue(child);
654                 }
655             }
656         }
657
658         void AttachEffect(Effect effect)
659         {
660             if (_effectControlProvider == null)
661                 return;
662             if (effect.IsAttached)
663                 throw new InvalidOperationException("Cannot attach Effect to multiple sources");
664
665             Effect effectToRegister = effect;
666             if (effect is RoutingEffect)
667                 effectToRegister = ((RoutingEffect)effect).Inner;
668             _effectControlProvider.RegisterEffect(effectToRegister);
669             effectToRegister.Element = this;
670             effect.SendAttached();
671         }
672
673         void EffectsOnClearing(object sender, EventArgs eventArgs)
674         {
675             foreach (Effect effect in _effects)
676             {
677                 effect?.ClearEffect();
678             }
679         }
680
681         void EffectsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
682         {
683             switch (e.Action)
684             {
685                 case NotifyCollectionChangedAction.Add:
686                     foreach (Effect effect in e.NewItems)
687                     {
688                         AttachEffect(effect);
689                     }
690                     break;
691                 case NotifyCollectionChangedAction.Move:
692                     break;
693                 case NotifyCollectionChangedAction.Remove:
694                     foreach (Effect effect in e.OldItems)
695                     {
696                         effect.ClearEffect();
697                     }
698                     break;
699                 case NotifyCollectionChangedAction.Replace:
700                     foreach (Effect effect in e.NewItems)
701                     {
702                         AttachEffect(effect);
703                     }
704                     foreach (Effect effect in e.OldItems)
705                     {
706                         effect.ClearEffect();
707                     }
708                     break;
709                 case NotifyCollectionChangedAction.Reset:
710                     if (e.NewItems != null)
711                     {
712                         foreach (Effect effect in e.NewItems)
713                         {
714                             AttachEffect(effect);
715                         }
716                     }
717                     if (e.OldItems != null)
718                     {
719                         foreach (Effect effect in e.OldItems)
720                         {
721                             effect.ClearEffect();
722                         }
723                     }
724                     break;
725                 default:
726                     throw new ArgumentOutOfRangeException();
727             }
728         }
729
730         INameScope GetNameScope()
731         {
732             INameScope namescope = NameScope.GetNameScope(this);
733             Element p = RealParent;
734             while (namescope == null && p != null)
735             {
736                 namescope = NameScope.GetNameScope(p);
737                 p = p.RealParent;
738             }
739             return namescope;
740         }
741
742         void OnDescendantAdded(Element child)
743         {
744             DescendantAdded?.Invoke(this, new ElementEventArgs(child));
745
746             if (RealParent != null)
747                 RealParent.OnDescendantAdded(child);
748         }
749
750         void OnDescendantRemoved(Element child)
751         {
752             DescendantRemoved?.Invoke(this, new ElementEventArgs(child));
753
754             if (RealParent != null)
755                 RealParent.OnDescendantRemoved(child);
756         }
757
758         void OnResourceChanged(BindableProperty property, object value)
759         {
760             SetValueCore(property, value, SetValueFlags.ClearOneWayBindings | SetValueFlags.ClearTwoWayBindings);
761         }
762     }
763 }